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
变量)
答案 0 :(得分:85)
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环境中未在后台执行的管道的最后一个命令。
因此,在脚本中使用类似的内容会使循环后修改后的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中answer所述,您有时可以使用here string:
while read i; do echo $i; done <<< "$FILECONTENT"
这不需要shopt
;您可以使用它保存进程。
答案 1 :(得分:25)
Jonathan Leffler explains如何使用process substitution执行您想要的操作,但另一种可能性是使用here string:
while read i; do echo "$i"; done <<<"$FILECONTENT"
这可以节省一个过程。
答案 2 :(得分:0)
此功能使jpg文件(bash)重复$ NUM次
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
}