Bash管道命令输出到sum循环

时间:2015-01-28 20:01:15

标签: bash piping

进入bash,我喜欢它,但似乎有许多细微之处最终会在功能方面产生重大影响,而且无论如何,这是我的问题:

我知道这有效:

total=0
for i in $(grep number some.txt | cut -d " " -f 1); do
    (( total+=i ))
done

但为什么不这样呢?:

grep number some.txt | cut -d " " -f 1 | while read i; do (( total+=i )); done

some.txt:

1 number
2 number
50 number

for和while循环分别接收1,2和50,但for循环显示总变量最终为53,而在while循环代码中,它只保持为零。我知道我在这里缺少一些基本知识,请帮助我。

例如,我也没有发现管道上的差异 如果我跑

grep number some.txt | cut -d " " -f 1 | while read i; echo "-> $i"; done

我得到了预期的输出

-> 1
-> 2
-> 50

但如果这样跑

while read i; echo "-> $i"; done <<< $(grep number some.txt | cut -d " " -f 1)

然后输出变为

-> 1 2 50

这对我来说似乎很奇怪,因为grep会在单独的行中输出结果。好像这不是模棱两可的,如果我的文件中只有数字1 2 3在不同的行中,我就跑了

while read i; echo "-> $i"; done < someother.txt

然后输出将由不同行中的回波打印,如前面示例中所预期的那样。我知道&lt;用于文件和&lt;&lt;&lt;对于命令输出,但为什么存在这种线差异?

无论如何,我希望有人能对此事有所了解,谢谢你的时间!

1 个答案:

答案 0 :(得分:6)

grep number some.txt | cut -d " " -f 1 | while read i; do (( total+=i )); done

管道中的每个命令都在子shell中运行。这意味着当您将while read循环放入管道中时,任何变量赋值都将丢失。

请参阅:BashFAQ 024 - "I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?"

while read i; echo "-> $i"; done <<< "$(grep number some.txt | cut -d " " -f 1)"

要保留grep的换行符,请添加双引号。否则$(...)的结果会受到分词的影响,将所有空格折叠成单个空格。