Перебор многострочной строки, хранящейся в переменной

17

Я читал, что это плохо писать что-то вроде for line in $(command): правильный путь выглядит так:

command | while IFS= read -r line; do echo $line; done

Это прекрасно работает. Но что, если я хочу перебрать содержимое переменной , а не прямой результат команды?

Например, представьте, что вы создали следующий файл quickfox:

The quick brown
foxjumps\ over -
the
lazy ,
dog.

Я хотел бы иметь возможность сделать что-то вроде этого:

# This is just for the example,
# I could of course stream the contents to `read`
variable=$(cat quickfox);
while IFS= read -r line < $variable; do echo $line; done; # this is incorrect
Sheljohn
источник

Ответы:

19

В современных оболочках, таких как bash и zsh, у вас есть очень полезный перенаправитель `<<< ', который принимает строку в качестве входных данных. Так вы бы сделали

while IFS= read -r line ; do echo $line; done <<< "$variable"

В противном случае вы всегда можете сделать

echo "$variable" | while IFS= read -r line ; do echo $line; done
lgeorget
источник
Извините, я должен был подумать о том, чтобы повторить содержание, конечно. Но все равно спасибо за быстрый ответ!
Шелджон
1
вам нужно использовать двойные кавычки $variableпри использовании, иначе whileцикл получит только одну строку ввода. Смотрите, например, разница в выходе между echo $variableпротив echo "$variable"или cat <<< $variableпротив cat <<< "$variable".
cas
@cas На самом деле это зависит от того, что находится внутри переменной $. В случае, представленном OP («variable = $ (cat quickfox)»), он работает без дополнительных кавычек. Но в общем случае вы правы. Я редактирую свой ответ. Благодарю.
lgeorget
Сам variable=$(cat quickfox)вопрос ОП приводит пример того, о чем я говорил. Использование этого $variableв двойных кавычках включает в себя переводы строк, при использовании его без перевода строки переводятся в пробелы оболочкой. Если вы читаете и обрабатываете построчно, это имеет огромное значение - в первом случае у вас есть несколько строк ввода, а во втором - только одна строка ввода. Входные данные внешне схожи, но на практике совершенно различны в этих двух случаях.
Cas
например: с этими входными данными cat <<< "$variable" | wc -lвозвращает 5. cat <<< $variable | wc -lвозвращает 1. Если вы хотите / должны сохранить пробел (включая символы новой строки, табуляции, одиночные или множественные пробелы) в переменной, то вы ДОЛЖНЫ заключить двойную кавычку в переменную, когда вы ее используете, в противном случае все они будут превращены в один пробел между каждым «словом».
Cas