【问题标题】:Bash piping command output into sum loopBash管道命令输出到sum循环
【发布时间】:2015-01-28 20:01:15
【问题描述】:

进入 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

一些.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

然后输出将由 echo 在不同的行中打印,正如前面示例中所预期的那样。我知道

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

【问题讨论】:

  • 作为第二个问题的简单示例,请尝试:a=$'foo\nbar'; echo $a; echo ===; echo "$a; echo ===; cat &lt;&lt;&lt;$a; echo ===; cat &lt;&lt;&lt;"$a"
  • 您也可以使用awk计算第一列的总和:awk '{a+=$1} END {print a}' some.txt

标签: bash piping


【解决方案1】:
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 的换行符,请添加双引号。否则$(...) 的结果会受到分词的影响,这会将所有空格折叠成单个空格。

【讨论】:

  • 另一种选择是set +m; shopt -s lastpipe,但这真的是在搅浑水。
猜你喜欢
  • 2018-01-25
  • 2015-12-07
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多