Как правильно перебирать строки в bash либо в переменной, либо из вывода команды? Простая установка переменной IFS для новой строки работает для вывода команды, но не для обработки переменной, содержащей новые строки.
Например
#!/bin/bash
list="One\ntwo\nthree\nfour"
#Print the list with echo
echo -e "echo: \n$list"
#Set the field separator to new line
IFS=$'\n'
#Try to iterate over each line
echo "For loop:"
for item in $list
do
echo "Item: $item"
done
#Output the variable to a file
echo -e $list > list.txt
#Try to iterate over each line from the cat command
echo "For loop over command output:"
for item in `cat list.txt`
do
echo "Item: $item"
done
Это дает вывод:
echo:
One
two
three
four
For loop:
Item: One\ntwo\nthree\nfour
For loop over command output:
Item: One
Item: two
Item: three
Item: four
Как видите, при выводе переменной или итерации по cat
команде каждая строка выводится правильно. Однако первый цикл for печатает все элементы в одной строке. Есть идеи?
Ответы:
В bash, если вы хотите встроить строки в строку, заключите строку в
$''
:И если у вас уже есть такая строка в переменной, вы можете читать ее построчно с помощью:
источник
done <<< "$list"
имеет решающее значениеdone <<< "$list"
является решающей, потому что это передаст «$ list» в качестве входных данныхread
$list
очень важно.echo "$list" | while ...
может показаться более ясным, чем... done <<< "$line"
Вы можете использовать
while
+read
:Btw.
-e
возможностьecho
нестандартно. Используйтеprintf
вместо этого, если вы хотите переносимость.источник
<<<
версия, предложенная Гленном Джекманом , работает с присвоением переменных.while
часть.<<<
Версия не дает (в новых версиях Баша, по крайней мере).источник
IFS=$'\n'
для того же эффекта.Вот забавный способ сделать цикл for:
Немного более разумным / читабельным было бы:
Но это слишком сложно, вам нужно только место там:
Ваша
$line
переменная не содержит новых строк. Он содержит случаи,\
сопровождаемыеn
. Вы можете видеть это ясно с:Подстановка заменяет те пробелами, которых достаточно для работы циклов:
Демо-версия:
источник
cr
вы можете использовать$'\n'
.Вы также можете сначала преобразовать переменную в массив, а затем выполнить итерацию.
Это полезно только в том случае, если вы не хотите связываться с командой,
IFS
а также возникают проблемы сread
командой, как это может случиться, если вы вызовете другой скрипт внутри цикла, чтобы этот скрипт мог очистить буфер чтения перед возвратом, как это случилось со мной. ,источник