提问人:Wakan Tanka 提问时间:10/24/2013 最后编辑:codeforesterWakan Tanka 更新时间:8/1/2023 访问量:132448
如何将输入管道传递到 Bash while 循环并在循环结束后保留变量
How to pipe input to a Bash while loop and preserve variables after loop ends
问:
Bash 允许使用:cat <(echo "$FILECONTENT")
Bash 还允许使用:while read i; do echo $i; done </etc/passwd
要将前两者结合起来,可以使用:echo $FILECONTENT | while read i; do echo $i; done
最后一个的问题是它创建了子 shell,并且在 while 循环结束之后无法再访问变量。i
我的问题是:
如何实现这样的事情:或者换句话说:我怎么能确定它在循环时幸存下来?while read i; do echo $i; done <(echo "$FILECONTENT")
i
请注意,我知道将 while 语句封闭进去,但这并不能解决问题(想象一下,您想在函数中使用 while 循环并返回变量){}
i
答:
Process Substitution 的正确表示法是:
while read i; do echo $i; done < <(echo "$FILECONTENT")
然后,当循环终止时,循环中分配的最后一个值可用。
另一种选择是:i
echo $FILECONTENT |
{
while read i; do echo $i; done
...do other things using $i here...
}
大括号是 I/O 分组操作,本身不会创建子 shell。在此上下文中,它们是管道的一部分,因此作为子 shell 运行,但这是因为 ,而不是 .你在问题中提到了这一点。AFAIK,您可以从函数内部的这些内部进行返回。|
{ ... }
Bash 还提供了内置的 shopt
,它的众多选项之一是:
lastpipe
如果设置了作业控制,并且作业控制未处于活动状态,则 shell 将运行当前 shell 环境中未在后台执行的管道的最后一个命令。
因此,在脚本中使用类似这样的东西可以使修改后的 Modfied 在循环后可用:sum
FILECONTENT="12 Name
13 Number
14 Information"
shopt -s lastpipe # Comment this out to see the alternative behaviour
sum=0
echo "$FILECONTENT" |
while read number name; do ((sum+=$number)); done
echo $sum
在命令行中执行此操作通常会违反“作业控制未处于活动状态”(即,在命令行中,作业控制处于活动状态)。在不使用脚本的情况下对此进行测试失败。
此外,正如 Gareth Rees 在他的回答中指出的那样,您有时可以使用 here 字符串:
while read i; do echo $i; done <<< "$FILECONTENT"
这不需要 ;您可以使用它来保存进程。shopt
评论
while read i; do echo $i; done < <(cat /etc/passwd); echo $i
i
while read i; do x=$i; done < <(cat /etc/passwd); echo i=$i; echo x=$x
Jonathan Leffler 解释了如何使用进程替换来做你想做的事,但另一种可能性是使用 here 字符串:
while read i; do echo "$i"; done <<<"$FILECONTENT"
这样可以节省一个过程。
此函数使 jpg 文件重复$NUM次 (bash)
function makeDups() {
NUM=$1
echo "Making $1 duplicates for $(ls -1 *.jpg|wc -l) files"
ls -1 *.jpg|sort|while read f
do
COUNT=0
while [ "$COUNT" -le "$NUM" ]
do
cp $f ${f//sm/${COUNT}sm}
((COUNT++))
done
done
}
最快的是:
while read -r ITEM; do
OPERATION
done < <(COMMAND)
或者用一行:
while read -r ITEM; do OPERATION; done < <(COMMAND)
Bash 提供 var 默认行为,因此:
while read -r line
do
total=${total:-0}
total=$((total + $(calculation code)))
done
echo $total
这允许循环轻松捕获脚本和函数的 stdin。
评论
lastpipe