AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 468177
Accepted
Martin Vegter
Martin Vegter
Asked: 2018-09-11 22:41:34 +0800 CST2018-09-11 22:41:34 +0800 CST 2018-09-11 22:41:34 +0800 CST

破折号:从管道中读取变量

  • 772

在bashorzsh中,我可以使用以下语法从管道读取变量:

echo AAA BBB | read X Y ; echo $X

这将打印AAA

为什么同样不起作用/bin/sh?

我在 Debian 中使用/bin/sh-> /bin/dash dash

shell dash
  • 4 4 个回答
  • 3497 Views

4 个回答

  • Voted
  1. Best Answer
    pLumo
    2018-09-11T22:48:58+08:002018-09-11T22:48:58+08:00

    为什么在 '/bin/sh' 中同样不起作用?

    在管道中分配变量不能按预期工作sh,bash因为管道的每个命令都在子 shell 中运行。实际上,该命令确实有效X并被声明,Y但它们在管道之外不可用。

    以下将起作用:

    echo AAA BBB | { read X Y ; echo $X; }
    

    但在你的情况下:

    尝试这个,

    read X Y <<< "AAA BBB"
    

    或者

    read X Y < <(echo "AAA BBB")
    

    一些有用的链接:

    • http://mywiki.wooledge.org/BashFAQ/024
    • bash:从管道分配变量?
    • 从管道将值读入 shell 变量
    • 5
  2. ilkkachu
    2018-09-12T00:27:15+08:002018-09-12T00:27:15+08:00

    在 bash 或 zsh 中,我可以使用以下语法从管道读取变量。

    echo AAA BBB | read X Y ; echo $X
    

    不,你不能。默认设置下不在 Bash 中。

    $ ./bash5.0-alpha -c 'echo AAA BBB | read X Y ; echo "Bash=$BASH_VERSION X=\"$X\""'
    Bash=5.0.0(1)-alpha X=""
    $ bash -c 'echo AAA BBB | read X Y ; echo "Bash=$BASH_VERSION X=\"$X\""'
    Bash=4.4.12(1)-release X=""
    

    Bash 在单独的子 shell 环境中运行管道中的所有命令,因此对 shell 变量的更改在管道之外不可见。破折号在这里是相似的。

    Zsh 和 ksh(AT&T 实现,不是pdksh或衍生品)在主 shell 环境中运行管道的最后一个命令,因此可以正常工作:

    $ zsh -c 'echo AAA BBB | read X Y ; echo "Zsh=$ZSH_VERSION X=\"$X\""'
    Zsh=5.3.1 X="AAA"
    

    在 Bash 中,您可以shopt -s lastpipe让它做 ksh 和 zsh 所做的事情(尽管仅适用于非交互式 shell):

    $ bash -O lastpipe -c 'echo AAA BBB | read X Y ; echo "Bash=$BASH_VERSION X=\"$X\""'
    Bash=4.4.12(1)-release X="AAA"
    

    但我认为 Dash 没有这样的选择。

    在 Bash 中,您也可以使用进程替换而不是管道,但这在 Dash 中也不是一个选项。


    解决方法将围绕使循环的右侧成为复合语句或函数,因此在读取管道的相同环境中使用从管道读取的值。

    $ dash -c 'echo AAA BBB | { read X Y ; echo "X=\"$X\""; } '
    X="AAA"
    $ dash -c 'f() { read X Y ; echo "X=\"$X\""; }; echo AAA BBB | f'
    X="AAA"
    

    或使用此处的文档:

    read X Y << EOF
    $(echo AAA BBB)
    EOF
    
    • 2
  3. user232326
    2018-09-12T01:43:52+08:002018-09-12T01:43:52+08:00

    不,这不会设置 X 和 Y(在分号之后)。

    echo AAA BBB | read X Y ; echo $X
    
    $ bash -c 'echo AAA BBB | read X Y ; echo "<$X>"'
    <>
    

    破折号也是如此。

    要让它在破折号中工作,您需要求助于较旧的解决方案(here-doc):

    $ read X Y <<_EOT_
    > AAA BBB
    > _EOT_
    $ echo "<$X>"
    <AAA>
    

    作为尝试 shell 的命令(遗憾的是不能删除换行符(没有单行)):

    $ bash -c 'read X Y <<_EOT_
    AAA BBB
    _EOT_
    echo "<$X>" '
    <AAA>
    

    这在 dash、zsh、ksh 和许多其他程序中的工作方式完全相同:

    $ dash -c 'read X Y <<_EOT_
    AAA BBB
    _EOT_
    echo "<$X>" '
    <AAA>
    

    可能here-doc是:

    1. 这里字符串(适用于 bash、ksh、zsh):

      $ bash -c 'read X Y <<<"AAA BBB"; echo "<$X>" '
      <AAA>
      
    2. 进程替换(适用于 bash、ksh、zsh):

      $ bash -c 'read X Y < <(echo AAA BBB) ; echo "<$X>" '
      <AAA>
      

    打印值并在 dash 中工作但不将变量设置为 dash 或 bash(但在 ksh 和 zsh 中)的替代方法是:

    1. 组命令:

      $ dash -c 'echo "AAA BBB" | { read X Y ; echo "<$X>"; }; echo "<$X>" '
      <AAA>
      <>
      

      请注意,最后一个解决方案可以设置为使用lastpipe选项(不用于交互使用)或默认情况下在 ksh/zsh 中设置变量:

      $ bash -c 'shopt -s lastpipe;echo "AAA BBB"|{ read X Y;echo "1<$X>"; };echo "2<$X>"'
      1<AAA>
      2<AAA>
      
      $ ksh -c 'echo "AAA BBB"|{ read X Y;echo "1<$X>"; };echo "2<$X>"'
      1<AAA>
      2<AAA>
      
      $ zsh -c 'echo "AAA BBB"|{ read X Y;echo "1<$X>"; }; echo "2<$X>"'
      1<AAA>
      2<AAA>
      
    • 0
  4. schily
    2018-09-11T23:45:15+08:002018-09-11T23:45:15+08:00

    小心管道中进程的变量分配。POSIX 标准不需要特定的行为。

    现代 shellksh93和最新版本的Bourne Shell让主 shell 成为管道中两个进程的父进程,如果最右边的进程是内置命令,这个命令甚至在主 shell 中运行。

    另一种变体是使用上述方法,但始终在另一个进程中运行最右边的命令。

    旧版本是原始 Bourne Shell 的工作方式:shell 分叉,分叉的进程从管道创建所有其他进程,最后转换为最右边的进程。

    最后一个版本需要的代码比其他版本少得多,但速度较慢。由于代码大小,这是在 1976 年使用的。

    第一个变体是最快的变体,但需要比其他变体更多的代码,但它是唯一在原始 shell 进程中运行变量赋值的变体,它需要在主 shell 中具有修改后的变量值。

    • -2

相关问题

  • 这个命令是如何工作的?mkfifo /tmp/f; 猫/tmp/f | /bin/sh -i 2>&1 | 数控 -l 1234 > /tmp/f

  • FreeBSD 的 sh:列出函数

  • 有没有办法让 ls 只显示某些目录的隐藏文件?

  • grep -v grep 有什么作用

  • 如何将带有〜的路径保存到变量中?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve