Что относительно read
в a while
цикл?
some command returning multiple lines | while IFS= read -r line ; do
echo "$line"
done
Будьте осторожны, тем не менее, канал выполняется в подоболочке, что означает, что Вы не можете изменить значения переменных для остальной части сценария. При необходимости в чем-то для выживания от цикла с условием продолжения, можно использовать замену процесса удара:
while IFS= read -r line ; do
let var+=line
done < <(some command returning multiple lines)
echo "$var"
Установка IFS
только к новой строке недостаточно. (Почему Вы также разделяете в символах возврата, между прочим?),
В Вашем коде, ${ROWS[@]}
(который является странным способом записать $ROWS
— ROWS
не массив), не дважды заключается в кавычки. (Если бы это были внутренние двойные кавычки, то Вы получили бы единственную строку с тех пор ROWS
не массив.), Таким образом, оболочка разделяет значение переменной в поля в каждом IFS
символ, затем рассматривает каждое поле как шаблон шарика. Например, если одна из строк, распечатанных командой, содержит отдельный символ *
, это будет заменено именами файлов в текущем каталоге.
Можно выключить globbing с set -f
. В большинстве случаев, где Вы устанавливаете IFS
для использования полевой функции разделения оболочки также необходимо выключить globbing. Задержите его на с set +f
.
Надежная идиома для чтения вывода команды линию за линией while IFS= read -r
.
some command returning multiple lines |
while IFS= read -r ROW; do
…
done
Обратите внимание, что большинство оболочек выполняет каждую команду конвейера в отдельной подоболочке. Таким образом, если необходимо установить переменные и использовать их после цикла, перенести эти команды в группу вместе с циклом. (Ksh и zsh являются исключениями, они выполняют последнюю команду конвейера в родительской оболочке.)
some command returning multiple lines | {
while IFS= read -r ROW; do
…
row_count=$((row_count+1))
done
echo "There were $row_count rows."
}
Вы смешиваете здесь-документ и здесь-представляете-в-виде-строки синтаксис в Вашем вопросе об обновлении.
Любой здесь-документ использования:
while IFS= read -r line ; do
let var+=line #line 42
done <<ENDMARK
$(sqlite3 -list -nullvalue NULL -separator ',' /var/log/asterisk/master.db "${QUERY}")
ENDMARK
Или здесь-строка:
while IFS= read -r line ; do
let var+=line #line 42
done <<< $(sqlite3 -list -nullvalue NULL -separator ',' /var/log/asterisk/master.db "${QUERY}")
bash
, но стоит отметить, что обзор подоболочки переменных является только проблемой вbash
, выполнение в том же самомzsh
не имел бы этой проблемы вообще. – Caleb 12.09.2012, 01:28