击:为什么管道输入到"读"而读..."只有当送入&QUOT工程;构造? [英] Bash: Why piping input to "read" only works when fed into "while read ..." construct?
问题描述
我一直想读这样的投入环境变量,从程序的输出:
I've been trying to read input into environment variables from program output like this:
echo first second | read A B ; echo $A-$B
和结果是:
-
A和B都总是空的。我读到的bash在子shell执行管道命令和基本preventing一个来自管道输入读取数据。但是,以下
Both A and B are always empty. I read about bash executing piped commands in sub-shell and that basically preventing one from piping input to read. However, the following:
echo first second | while read A B ; do echo $A-$B ; done
似乎工作,其结果是:
Seems to work, the result is:
first-second
有人能解释什么是这里的逻辑是什么?难道这里面的命令,而
... 完成
构造在同一外壳实际执行为回声
,而不是在一个子shell?
Can someone please explain what is the logic here? Is it that the commands inside the while
... done
construct are actually executed in the same shell as echo
and not in a sub-shell?
推荐答案
在庆典(和其他的外壳也),当你管什么 |
到另一个命令,你会隐含创建的叉的,一个子shell谁是本届会议的一个孩子,谁也不能影响当前会话的ENVIRON
How to do a loop against stdin and get result stored in a variable
Under bash (and other shell also), when you pipe something by using |
to another command, you will implicitely create a fork, a subshell who's a child of current session and who can't affect current session's environ.
所以这个:
TOTAL=0
printf "%s %s\n" 9 4 3 1 77 2 25 12 226 664 |
while read A B;do
((TOTAL+=A-B))
printf "%3d - %3d = %4d -> TOTAL= %4d\n" $A $B $[A-B] $TOTAL
done
echo final total: $TOTAL
不会给预期的结果:
won't give expected result:
9 - 4 = 5 -> TOTAL= 5
3 - 1 = 2 -> TOTAL= 7
77 - 2 = 75 -> TOTAL= 82
25 - 12 = 13 -> TOTAL= 95
226 - 664 = -438 -> TOTAL= -343
echo final total: $TOTAL
final total: 0
如果计算的 TOTAL 的could'nt在主脚本中重复使用。
Where computed TOTAL could'nt be reused in main script.
使用庆典的进程替换的在这里,文件的或的这里字符串的,你可以逆叉:
By using bash Process Substitution, Here Documents or Here Strings, you could inverse the fork:
read A B <<<"first second"
echo $A
first
echo $B
second
在这里的文档
while read A B;do
echo $A-$B
C=$A-$B
done << eodoc
first second
third fourth
eodoc
first-second
third-fourth
在循环外部:
echo : $C
: third-fourth
在这里命令
tot=0
while read A B ;do
echo $((A-B))
((tot+=A-B))
done < <(
printf "%s %s\n" 9 4 3 1 77 2 25 12 226 664
)
5
2
75
13
-438
# and finally out of loop:
echo $tot
-343
管道连接到的命令列表的
但只是针对工作的标准输入的,您可以创建一种脚本到的叉的:
Piping to a command list
But for working only against stdin, you may create a kind of script into the fork:
printf "%s %s\n" 9 4 3 1 77 2 25 12 226 664 | {
while read A B;do
((TOTAL+=A-B));
printf "%3d - %3d = %4d -> TOTAL= %4d\n" $A $B $[A-B] $TOTAL;
done
echo "Out of the loop total:" $TOTAL
}
会给:
9 - 4 = 5 -> TOTAL= 5
3 - 1 = 2 -> TOTAL= 7
77 - 2 = 75 -> TOTAL= 82
25 - 12 = 13 -> TOTAL= 95
226 - 664 = -438 -> TOTAL= -343
Out of the loop total: -343
请注意: $ TOTAL
无法在主脚本的(后右花括号} $ C使用$ C>)。
Note: $TOTAL
could not be used in main script (after right curly bracket }
).
由于@CharlesDuffy正确地指出的那样,是用来改变这种行为一个bash选项。但对于这一点,我们必须先停用 作业控制的:
As @CharlesDuffy correctly pointed out, there is a bash option used to change this behaviour. But for this, we have to first disable job control:
shopt -s lastpipe # Set *lastpipe* option
set +m # Disabling job control
TOTAL=0
printf "%s %s\n" 9 4 3 1 77 2 25 12 226 664 |
while read A B;do
((TOTAL+=A-B))
printf "%3d - %3d = %4d -> TOTAL= %4d\n" $A $B $[A-B] $TOTAL
done
9 - 4 = 5 -> TOTAL= -338
3 - 1 = 2 -> TOTAL= -336
77 - 2 = 75 -> TOTAL= -261
25 - 12 = 13 -> TOTAL= -248
226 - 664 = -438 -> TOTAL= -686
echo final total: $TOTAL
-343
这将工作,但我(个人)不喜欢这个,因为这不是的标准的,并不会有助于使脚本的可读性。同时禁用作业控制看起来很贵访问此行为。
This will work, but I (personally) don't like this because this is not standard and won't help to make script readable. Also disabling job control seem expensive for accessing this behaviour.
注意: 作业控制的默认情况下,只有在的交互的会话启用。因此,组+ M
不要求在正常的脚本。
Note: Job control is enabled by default only in interactive sessions. So set +m
is not required in normal scripts.
所以忘了在脚本会产生,如果运行控制台或在脚本中运行不同的行为设定+ M
。这会不会让这个容易理解和调试...
So forgotten set +m
in a script would create different behaviours if run in a console or if run in a script. This will not going to make this easy to understand or to debug...
这篇关于击:为什么管道输入到&QUOT;读&QUOT;而读...&QUOT;只有当送入&QUOT工程;构造?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!