我试图让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=
Run Code Online (Sandbox Code Playgroud)
我想要输出的地方test=hello world
.我试过把""引号括起来"$test"
也不起作用.
yar*_*ena 159
使用
IFS= read var << EOF
$(foo)
EOF
Run Code Online (Sandbox Code Playgroud)
你可以欺骗read
从这样的管道接受:
echo "hello world" | { read test; echo test=$test; }
Run Code Online (Sandbox Code Playgroud)
甚至写一个这样的函数:
read_from_pipe() { read "$@" <&0; }
Run Code Online (Sandbox Code Playgroud)
但没有意义 - 你的变量任务可能不会持久!管道可以生成子shell,其中环境由值继承,而不是通过引用继承.这就是为什么read
不打扰来自管道的输入 - 它是未定义的.
仅供参考,http://www.etalabs.net/sh_tricks.html是为了对抗伯恩贝壳的奇怪和不相容性所必需的琐事.
Nic*_*ick 105
如果你想要读取大量数据并分别在每一行上工作,你可以使用这样的东西:
cat myFile | while read x ; do echo $x ; done
Run Code Online (Sandbox Code Playgroud)
如果你想将这些行分成多个单词,你可以使用多个变量代替x,如下所示:
cat myFile | while read x y ; do echo $y $x ; done
Run Code Online (Sandbox Code Playgroud)
或者:
while read x y ; do echo $y $x ; done < myFile
Run Code Online (Sandbox Code Playgroud)
但是一旦你开始想要做任何非常聪明的事情,你最好选择像perl这样的脚本语言,你可以尝试这样的事情:
perl -ane 'print "$F[0]\n"' < myFile
Run Code Online (Sandbox Code Playgroud)
perl(或者我猜这些语言中的任何一种语言)有一个相当陡峭的学习曲线但是如果你想做除了最简单的脚本之外的任何事情,从长远来看你会发现它更容易.我推荐Perl Cookbook,当然还有Larry Wall等人的Perl编程语言.
Pau*_*ce. 40
read
不会从管道中读取(或者由于管道创建子壳,结果可能会丢失).但是,您可以在Bash中使用here字符串:
$ read a b c <<< $(echo 1 2 3)
$ echo $a $b $c
1 2 3
Run Code Online (Sandbox Code Playgroud)
小智 39
这是另一种选择
$ read test < <(echo hello world)
$ echo $test
hello world
Run Code Online (Sandbox Code Playgroud)
dja*_*ski 30
我不是Bash的专家,但我想知道为什么没有提出这个:
stdin=$(cat)
echo "$stdin"
Run Code Online (Sandbox Code Playgroud)
单线证明它对我有用:
$ fortune | eval 'stdin=$(cat); echo "$stdin"'
Run Code Online (Sandbox Code Playgroud)
che*_*ner 25
bash
4.2引入了一个lastpipe
选项,它允许您的代码按照写入的方式工作,方法是在当前shell的管道中执行最后一个命令,而不是子shell.
shopt -s lastpipe
echo "hello world" | read test; echo test=$test
Run Code Online (Sandbox Code Playgroud)
Sef*_*eff 15
一个可以从 PIPE 和命令行参数读取数据的智能脚本:
#!/bin/bash
if [[ -p /dev/stdin ]]
then
PIPE=$(cat -)
echo "PIPE=$PIPE"
fi
echo "ARGS=$@"
Run Code Online (Sandbox Code Playgroud)
输出:
$ bash test arg1 arg2
ARGS=arg1 arg2
$ echo pipe_data1 | bash test arg1 arg2
PIPE=pipe_data1
ARGS=arg1 arg2
Run Code Online (Sandbox Code Playgroud)
说明:当脚本通过管道接收任何数据时,/dev/stdin(或 /proc/self/fd/0)将是管道的符号链接。
/proc/self/fd/0 -> pipe:[155938]
Run Code Online (Sandbox Code Playgroud)
如果没有,它将指向当前终端:
/proc/self/fd/0 -> /dev/pts/5
Run Code Online (Sandbox Code Playgroud)
bash[[ -p
选项可以检查它是否是管道。
cat -
读取自stdin
.
如果我们cat -
在没有时使用stdin
,它将永远等待,这就是我们将它放在if
条件中的原因。
mob*_*mob 13
从shell命令到bash变量的隐式管道的语法是
var=$(command)
Run Code Online (Sandbox Code Playgroud)
要么
var=`command`
Run Code Online (Sandbox Code Playgroud)
在您的示例中,您将数据传递给赋值语句,该语句不期望任何输入.
第一次尝试非常接近.这种变化应该有效:
echo "hello world" | { test=$(< /dev/stdin); echo "test=$test"; };
Run Code Online (Sandbox Code Playgroud)
输出是:
test =你好世界
在管道之后需要括号来包含要测试的分配和回声.
没有大括号,测试(在管道之后)的分配在一个shell中,而echo"test = $ test"在一个单独的shell中,它不知道该分配.这就是为什么你在输出中得到"test ="而不是"test = hello world".
在我看来,在bash中从stdin读取的最佳方法是以下方法,它还允许您在输入结束之前处理行:
while read LINE; do
echo $LINE
done < /dev/stdin
Run Code Online (Sandbox Code Playgroud)
因为我爱上了它,所以我想写个便条。我找到了这个线程,因为我必须重写一个旧的sh脚本才能与POSIX兼容。这基本上意味着通过重写如下代码来避免POSIX引入的管道/子外壳问题:
some_command | read a b c
Run Code Online (Sandbox Code Playgroud)
变成:
read a b c << EOF
$(some_command)
EOF
Run Code Online (Sandbox Code Playgroud)
像这样的代码:
some_command |
while read a b c; do
# something
done
Run Code Online (Sandbox Code Playgroud)
变成:
while read a b c; do
# something
done << EOF
$(some_command)
EOF
Run Code Online (Sandbox Code Playgroud)
但是后者在空输入时的行为并不相同。使用旧的表示法时,while循环不会在空输入中输入,但是在POSIX表示法中是!我认为这是由于EOF之前的换行符所致,因此不能忽略。行为更像旧符号的POSIX代码如下所示:
while read a b c; do
case $a in ("") break; esac
# something
done << EOF
$(some_command)
EOF
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,这应该足够好。但是不幸的是,如果some_command打印一个空行,它的行为仍然与旧记法并不完全一样。在旧的表示法中,while主体被执行,而在POSIX表示法中,我们在主体的前面中断。
解决此问题的方法可能如下所示:
while read a b c; do
case $a in ("something_guaranteed_not_to_be_printed_by_some_command") break; esac
# something
done << EOF
$(some_command)
echo "something_guaranteed_not_to_be_printed_by_some_command"
EOF
Run Code Online (Sandbox Code Playgroud)
将某些内容通过管道输送到涉及赋值的表达式中的行为并非如此。
相反,请尝试:
test=$(echo "hello world"); echo test=$test
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
302204 次 |
最近记录: |