seq 3 | x=<put some code here>
注意:这不是一个答案,尽管可能在功能上与之等效:
x=`seq 3`
由于seq 3
不在管道的左侧,因此会出现错误。
对于这个问题,请忽略变量内存超限的可能性,尽管管道确实可能会导致这种情况。
seq 3 | x=<put some code here>
注意:这不是一个答案,尽管可能在功能上与之等效:
x=`seq 3`
由于seq 3
不在管道的左侧,因此会出现错误。
对于这个问题,请忽略变量内存超限的可能性,尽管管道确实可能会导致这种情况。
为了补充 Charles Duffy 的有用回答,并聚焦于在 bash
中使其实际运行:
默认情况下,在 Bash v4.1- 中任何多段管道中的变量创建/修改都发生在 子shell 中,因此结果对调用 shell 不可见。
在 Bash v4.2+ 中,你可以设置选项lastpipe
以使最后一个管道段在当前 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,并且不需要调整全局选项。
bash
来说是最高效的。 - agc这在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可能会在同一个shell中执行第二行的read命令,以及第三行的echo命令 - 但是特别是bash不会这样做,除非启用了lastpipe shell选项。
设置变量最简单的方法是通过read
命令:
seq 3 | read -d '' x
这也适用于 zsh
,但不适用于 ksh
(ksh
中的 -d
选项不允许使用 NUL
)。
使用 x
的值的一种方法是在由管道创建的子shell中执行:
$ seq 3 | { read -d '' x; echo "$x"; }
1
2
3
$ seq 3 | read -d ':' x
$ echo "$x"
1
2
3
$ set +m; shopt -s lastpipe
$ seq 3 | read -d '' x
$ echo "$x"
1
2
3
使用 进程替换 :
$ read -d '' x < <(seq 3)
$ echo "$x"
1
2
3
$ read -d '' x <<-Hello
> $(seq 3)
> Hello
$ echo "$x"
1
2
3
或者,使用printf:
$ printf -v x "$(seq 3)"
$ echo "$x"
1
2
3
x
的值。这个概念后来被带到了 zsh
和(设置一些选项)到了 bash。详细信息已添加到答案中。 - user8017719< <(seq 3) read -r -d '' var
我完全不建议这样做。只需使用var=$(seq 3)
。
seq 3 && printf '\0'
放在进程替换符号的内部——这样当 seq
执行成功时,read
就会返回 true。以当前的代码写法,由于缺少尾部分隔符,它将返回 false,从而触发 set -e
、 ERR trap 等。 - Charles Duffy一种(修改后的)方法,可能不是最好的,而且根据我们的看法可能无法满足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; }
您可以使用临时文件:
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的答案,您不能在管道的右侧直接接收内容来存储变量。因此,为什么不使用外部位置将其作为副作用存储(而不是无副作用的管道)。
确保临时文件名未被其他程序使用。
seq 3 | { n=$(cat /dev/stdin) ; echo "$n" ; echo $n ; }
。 - agc
lastpipe
特性,该特性仅在作业控制处于非活动状态时才可用。 - Charles Duffyx=\
seq 3`(或者
x=$(seq 3)`) 这样的语句? - Ludonopex
只是会获取前一个命令的输出。 - Ludonope