2014-10-17 2 views
1

Функция getStrings(), которая вызывает функцию getPage(), которая возвращает некоторую страницу html. Этот html передается через egrep и sed, чтобы получить только 3 строки. Затем я пытаюсь поместить каждую строку в отдельную переменную link, profile, gallery, используя while read... Но он работает только внутри цикла 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

Исследовать 'shopt -s lastpipe'. –

ответ

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, который заставляет последнюю команду в конвейере запускаться в текущей оболочке, а не в подоболочку.

shopt -s lastpipe 
getPage $(getPageLink 1 $i) | egrep ... | while read line; do 
    ... 
done 

Однако, используя цикл, пока не лучший способ установить три переменные. Легче просто позвонить read три раза в командной группе, чтобы все они читались из одного потока. В любом из этих трех сценариев выше, замените время цикла с

{ read link; read profile; read gallery; } 

Если вы хотите быть немного более гибким, поставить имена переменных, которые вы можете прочитать в массиве:

fields=(link profile gallery) 

замените время цикла с этим в цикле вместо:

for var in "${fields[@]}"; do read $var; done 

Это позволяет легко настроить свой код, если трубопровод когда-либо возвращаться больше или меньше строк, простым редактированием в fields, чтобы иметь соответствующие имена полей.

0

еще один решение с использованием массива:

getStrings() { 
array_3=(`getPage | #some function 
    egrep | ...`) #pipe conveyor 
} 
Смежные вопросы