在bash
中,使用管道输入分配变量的最有效方法是什么 - 仅使用从左到右的语法?假设管道的左侧是seq 3
,所以我们想要:
seq 3 | x=<put some code here>
注意:虽然功能上可能相同,但不是答案:
x=`seq 3`
...因为seq 3
不在管道的左侧侧。
对于这个Q,请忽略超出变量内存的可能性,管道当然可以这样做。
答案 0 :(得分:8)
BashFAQ #24中详细介绍了这一点。
只有在引用它的代码也位于该管道的右侧时,您才能可靠地使用在管道右侧收集的变量
#!/bin/bash
echo "hello" | { read -r var; echo "Read value: $var"; }
echo "After the pipeline exited, var contains: $var"
典型输出是:
Read value: hello
After the pipeline exited, var contains:
POSIX sh规范既不要求也不排除在同一个shell中执行的管道的右侧,后者执行后续命令。因此,shell 可以在同一个shell中的第二行执行read
,在第三行执行echo
- 但是bash,具体来说,将不这样做,除非启用了lastpipe
shell选项。
答案 1 :(得分:5)
在bash
中重点关注使其正常工作来补充Charles Duffy's helpful answer:
默认情况下,在Bash v4.1- 上总是,(多段)管道中的任何变量创建/修改都发生在子shell < / strong>,以便调用shell无法看到结果。
在 Bash v4.2 + 中,您可以设置选项lastpipe
,使 last 管道段在< em> current shell,以便 可见的变量创建/修改。
要使用 交互式 shell ,您必须使用set +m
另外关闭作业控制。
这是一个完整的例子(Bash v4.2 +):
$ unset x; shopt -s lastpipe; set +m; seq 3 | x=$(cat); echo "$x"
1
2
3
那就是说,
x=$(seq 3)
(现代的x=`seq 3`
)相当简单 - 它符合POSIX标准,因此也适用于较旧的Bash版本,并且不需要摆弄全局选项。
答案 2 :(得分:2)
设置变量的最简单方法是read
它:
seq 3 | read -d '' x
这是自2.04开发以来bash特有的。可以在zsh
中使用,但不能在ksh
中使用。
但是,使用x
值的唯一方法是在管道创建的子shell中执行此操作:
$ seq 3 | { read -d '' x; echo "$x"; }
1
2
3
请注意,读取的退出条件是失败的(因为没有找到&#39;&#39;字符)。更多细节可以在Bash FAQ 24
中找到答案 3 :(得分:1)
如果您愿意通过“管道输入”和“从左到右的语法”灵活处理您的意思,那么您可以这样做。试试这个:
< <(seq 3) read -r -d '' var
我不推荐这个。完全没有。只需使用var=$(seq 3)
。
答案 4 :(得分:0)
一个(修订)方法,可能不是最好的方法,可能会失败OP标准,具体取决于我们如何看待它:
# load $x, echo it quoted, then unquoted.
seq 3 | { x=$(</dev/stdin) ; echo "$x" ; echo $x ; }
输出:
1
2
3
1 2 3
此cat
变体适用于POSIX shell(yash
,dash
):
seq 3 | { n=$(cat /dev/stdin) ; echo "$n" ; echo $n ; }
答案 5 :(得分:-1)
您可以使用一个临时文件:
seq 3 >/var/tmp/agc-bashvar1; x=$(cat /var/tmp/agc-bashvar1 ); echo x is $x
使用后将清除以下内容:
seq 3 >/var/tmp/agc-bashvar1; x=$(cat /var/tmp/agc-bashvar1 ); rm /var/tmp/agc-bashvar1
然后
echo x is $x
合理性:基于@ charles-duffy的答案,基于直接在管道右侧接收到的内容,您无法生存一个变量。因此,为什么不使用外部位置将其存储为副作用(与无副作用的管道相对)。
确保临时文件名未被其他程序使用。