2014-10-17 16 views
1

有一个getStrings()函数调用getPage()函数返回一些html页面。该HTML通过egrepsed组合来传递,只能获得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 
} 
+2

调查'禁用了javascript -s lastpipe'。 – 2014-10-17 18:51:34

回答

4

简单:不要运行在子进程:)

到循环实际上完成这一点,你可以使用进程替换。

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数组具有相应的字段名称。

0

还有一个解决使用数组:

getStrings() { 
array_3=(`getPage | #some function 
    egrep | ...`) #pipe conveyor 
}