Что делает IFS= в этом цикле bash: 'cat file / while IFS= read-R line; do ... done`

Я изучаю bash, и я видел эту конструкцию:

cat file | while IFS= read -r line;
do
    ...
done

может кто-нибудь объяснить, что IFS= делает? Я знаю, что это разделитель полей ввода, но почему он установлен в ничто?

1 ответов


IFS делает много вещей, но вы спрашиваете об этом конкретном цикле.

эффект в этом цикле заключается в сохранить ведущие и конечные пробелы на line. Чтобы проиллюстрировать, сначала наблюдайте с IFS, установленным в nothing:

$ echo " this   is a test " | while IFS= read -r line; do echo "=$line=" ; done
= this   is a test =

на line переменная содержит все пробелы, которые она получила на своем stdin. Теперь рассмотрим тот же оператор с IFS по умолчанию:

$ echo " this   is a test " | while read -r line; do echo "=$line=" ; done
=this   is a test=

в этой версии, пробелы внутреннего линия все еще сохраняется. Но, ведущие и замыкающие пробелы были удалены.

что значит -r у в read -r?

на предупреждает read от обработки обратной косой черты как специального символа.

чтобы проиллюстрировать, мы используем две команды Эха, которые поставляют две строки в while петли. Наблюдайте, что происходит с -r:

$ { echo 'this \ line is \' ; echo 'continued'; } | while IFS= read -r line; do echo "=$line=" ; done
=this \ line is \=
=continued=

теперь посмотрите, что происходит без -r:

$ { echo 'this \ line is \' ; echo 'continued'; } | while IFS= read line; do echo "=$line=" ; done
=this \ line is continued=

без -r, произошло два изменения. Во-первых, двойная обратная косая черта была преобразована в одну обратную косую черту. Во-вторых, обратная косая черта в конце первой строки интерпретировалась как символ продолжения строки, и две строки были объединены в одну.

в сумме, если вы хотите, чтобы обратные косые черты на входе имели особое значение, не используйте -r. Если вы хотите, чтобы обратные косые черты во входных данных принимались как простые символы, используйте -r.

несколько строк

С read принимает вход по одной строке за раз, IFS ведет себя влияет на каждую строку ввода нескольких строк так же, как это влияет на ввод одной строки. -r ведет себя аналогично, за исключением того, что без -r, несколько строк могут быть объединены в одну линию с помощью обратной косой черты, как показано выше.

поведение с множественным входным сигналом линии, однако, можно изменить drastically используя прочитанные -d флаг. -d изменяет символ разделителя, который read используется для отметки конца входной строки. Например, мы можем завершить строки символом табуляции:

$ echo $'line one \n line\t two \n line three\t ends here'
line one 
 line    two 
 line three      ends here
$ echo $'line one \n line\t two \n line three\t ends here' | while IFS= read -r -d$'\t' line; do echo "=$line=" ; done
=line one 
 line=
= two 
 line three=

здесь $'...' construct использовался для ввода специальных символов, таких как newline,\n и tab,\t. Наблюдайте это с -d$'\t', read делит свой вход на "строки" на основе символов вкладки. Все, что после последней вкладки игнорируется.

как отрегулировать больше всего сложные имена файлов

наиболее важным использованием функций, описанных выше, является обработка сложных имен файлов. Поскольку один символ, который не может отображаться в path / filenames, является нулевым символом, нулевой символ может использоваться для разделения списка имен файлов. В качестве примера:

while IFS= read -r -d $'' file
do
    # do something to each file
done < <(find ~/music -type f -print0)