2014-10-17 47 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 
}