我试图让bash处理来自stdin的数据,但没有运气。我的意思是以下工作都不做:

echo "hello world" | test=($(< /dev/stdin)); echo test=$test
test=

echo "hello world" | read test; echo test=$test
test=

echo "hello world" | test=`cat`; echo test=$test
test=

我希望输出为test=hello world。我尝试在“$test”周围加上“”引号,但也不起作用。


当前回答

我不是Bash方面的专家,但我想知道为什么没有人提出这个建议:

stdin=$(cat)

echo "$stdin"

一行程序证明它对我有效:

$ fortune | eval 'stdin=$(cat); echo "$stdin"'

其他回答

将一些内容输出到包含赋值的表达式中就不是这样了。

相反,尝试:

test=$(echo "hello world"); echo test=$test

从shell命令到bash变量的隐式管道的语法为

var=$(command)

or

var=`command`

在示例中,将数据输送到赋值语句,该语句不需要任何输入。

Read不会从管道中读取(或者可能因为管道创建了子shell而导致结果丢失)。然而,你可以在Bash中使用here字符串:

$ read a b c <<< $(echo 1 2 3)
$ echo $a $b $c
1 2 3

但是关于lastpipe的信息,请参阅@chepner的回答。

如果你想读入大量数据并分别处理每一行,你可以使用这样的方法:

cat myFile | while read x ; do echo $x ; done

如果你想把这些行分成多个单词,你可以使用多个变量来代替x,就像这样:

cat myFile | while read x y ; do echo $y $x ; done

另外:

while read x y ; do echo $y $x ; done < myFile

但是一旦你开始想要做一些真正聪明的事情,你最好选择一些脚本语言,比如perl,你可以尝试这样的事情:

perl -ane 'print "$F[0]\n"' < myFile

使用perl(或者我猜这些语言中的任何一种)有一个相当陡峭的学习曲线,但如果您想做任何事情,而不是最简单的脚本,从长远来看,您会发现它要容易得多。我推荐《Perl烹饪书》,当然还有Larry Wall等人写的《Perl编程语言》。

Use

IFS= read var << EOF
$(foo)
EOF

你可以像这样诱使read从管道中接受:

echo "hello world" | { read test; echo test=$test; }

或者写一个这样的函数:

read_from_pipe() { read "$@" <&0; }

但这没有意义——你的可变任务可能不会持久!管道可以生成子shell,其中环境是按值继承的,而不是按引用继承的。这就是为什么read不打扰管道的输入——它是未定义的。

仅供参考,http://www.etalabs.net/sh_tricks.html是一个漂亮的cruft收集必要的战斗奇怪和不兼容的伯恩炮弹,sh。