在bash中的子进程外使用变量
问题描述:
有一个getStrings()
函数调用getPage()
函数返回一些html页面。该HTML通过egrep
和sed
组合来传递,只能获得3个字符串。然后我尝试使用while read..
构造将每个字符串分别放入单独的变量link
,profile
,gallery
。但它仅适用于while...done
循环,因为它在子进程中运行。我应该怎么做才能在getStrings()
函数之外使用这些变量?在bash中的子进程外使用变量
getStrings() {
local i=2
local C=0
getPage $(getPageLink 1 $i) |
egrep *some expression that results in 3 strings* |
while read line; do
if (((C % 3) == 0)); then
link=$line
elif (((C % 3) == 1)); then
profile=$line
else
gallery=$line
fi
C=$((C+1)) #Counter
done
}
答
简单:不要运行在子进程:)
到循环实际上完成这一点,你可以使用进程替换。
while read line; do
...
done < <(getPage $(getPageLink 1 $i) | egrep ...)
对于好奇,一个POSIX兼容的方法是使用命名管道(其可能是bash
使用命名管道实现进程替换):
mkfifo pipe
getPage $(getPageLink 1 $i) | egrep ... > pipe &
while read line; do
...
done < pipe
开始在bash
4.2,你可以设置lastpipe
选项,这会导致管道中的最后一个命令在当前shell中运行,而不是在子shell中运行。
shopt -s lastpipe
getPage $(getPageLink 1 $i) | egrep ... | while read line; do
...
done
但是,使用while循环是不设置三个变量的最佳方式。在一个命令组中调用read
三次会更容易,因此它们都是从同一个流中读取的。在以上三种情形的,如果你想成为一个更灵活一点更换
{ read link; read profile; read gallery; }
while循环,把变量的名字,你可能想在一个阵列中读取数据:
fields=(link profile gallery)
然后用这个代替while循环for循环,而不是:
for var in "${fields[@]}"; do read $var; done
这使您可以轻松地调整你的代码,如果管道再回到更多或更少的线,只需要编辑的fields
数组具有相应的字段名称。
答
还有一个解决使用数组:
getStrings() {
array_3=(`getPage | #some function
egrep | ...`) #pipe conveyor
}
调查'禁用了javascript -s lastpipe'。 – 2014-10-17 18:51:34