我试图让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”周围加上“”引号,但也不起作用。
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。
一个智能脚本,可以从PIPE和命令行参数读取数据:
#!/bin/bash
if [[ -p /dev/stdin ]]
then
PIPE=$(cat -)
echo "PIPE=$PIPE"
fi
echo "ARGS=$@"
输出:
$ bash test arg1 arg2
ARGS=arg1 arg2
$ echo pipe_data1 | bash test arg1 arg2
PIPE=pipe_data1
ARGS=arg1 arg2
解释:当脚本通过管道接收任何数据时,/dev/stdin(或/proc/self/fd/0)将是到管道的符号链接。
/proc/self/fd/0 -> pipe:[155938]
如果不是,它将指向当前终端:
/proc/self/fd/0 -> /dev/pts/5
bash [[-p选项可以检查它是否是管道。
Cat -读取from stdin。
如果我们在没有stdin的情况下使用cat -,它将永远等待,这就是为什么我们把它放在If条件中。
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。
如果你想读入大量数据并分别处理每一行,你可以使用这样的方法:
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编程语言》。