Как перенаправить стандартный ввод инструкции `while` в файл?

Я изучаю скрипты оболочки, и у меня есть некоторые трудности с пониманием развития основных структур команд, необходимых для написания скрипта, особенно с помощью команд while , do и done .

Я знаю, что при перенаправлении стандартного ввода инструкции while из файла он останавливается после того, как весь файл будет прочитан (в этом случае файл читается по строкам, а текущая строка помещается в переменную, используемую read ):

 while read lig fich do ... done < fich 

означает ли это, что у нас есть полная текущая линия в fich ?

Например: этот скрипт принимает имя пользователя и строку в качестве аргументов, ищет файлы, принадлежащие имени пользователя и имя которого содержит строку:

 #usage nblign nom-utilisateur chaine find . -user $1 | grep $2 >temp while read lig temp do echo $lig "nombre de ligne" `wc -l < $lig`$ done < temp rm temp 

Здесь мой учитель оммитировал $ до лига, while это опечатка? Поскольку для получения результата команды или переменной необходимо использовать $ для ее получения.

2 Solutions collect form web for “Как перенаправить стандартный ввод инструкции `while` в файл?”

У вас есть несколько заблуждений. Прежде всего, формат while read ... do вы пытаетесь использовать:

 while read var; do ...; done < file 

И не

 while read var file; do ...; done < file 

В принципе, while read var; do ...; done < file while read var; do ...; done < file while read var; do ...; done < file будет читать каждую строку file и сохранять его как var . Все, что угодно между read и do , берется как переменная. Если вы даете более одной переменной, тогда строка будет разделена на пробелы (ну, по значению переменной $IFS которая является \t , \n и пробелом, по умолчанию) и сохраняется в указанных переменных. Как поясняется в help read :

Считывает одну строку со стандартного ввода или из дескриптора файла FD, если включена опция -u. Строка разделяется на поля как на разбиение слов, а первое слово присваивается первому NAME, второе слово – второму NAME и т. Д., С любыми остальными словами, назначенными последнему NAME.

Так, например:

 $ echo "foo bar baz zab" | while read v1 rest; do echo "v1:$v1, rest:$rest"; done v1:foo, rest:bar baz zab $ echo "foo bar baz zab" | while read v1 v2 rest; do echo "v1:$v1, v2:$v2, rest:$rest"; done v1:foo, v2:bar, rest:baz zab $ echo "foo bar baz zab" | while read v1 v2 v3 rest; do echo "v1:$v1, v2:$v2, v3:$v3, rest:$rest"; done v1:foo, v2:bar, v3:baz, rest:zab 

Как вы можете видеть выше, входная строка разделяется на столько переменных, сколько вы даете. Когда на входе меньше имен переменных, чем «слов», последняя переменная получает остальную часть строки. То же самое происходит при чтении из файла.

Затем переменные задаются с помощью var="foo" и считываются с использованием $var . Так что нет, ваш учитель был прав, вы не хотите $ когда переменная определяется. Поэтому, while read var корректен и while read $var ошибочно.

Итак, рабочая версия вашего скрипта, использующая ту же логику, будет:

 find . -user $1 | grep $2 >temp while read lig do echo $lig "nombre de ligne" `wc -l < $lig` done < temp rm temp 

Обратите внимание, что я удалил temp точку из read и $ с конца echo строки. Я понятия не имею, почему вы так выразились.

Лучшая версия вашего скрипта, с правильными котировками ваших переменных, с помощью find для поиска соответствующих файлов вместо попыток разбора и без лишних временных файлов:

 find . -user "$1" -name "*$2*" | ## No need for a temp file, just pipe the output directly ## to the while loop while read lig do echo "$lig nombre de ligne: $(wc -l < "$lig")" done 

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

 find . -user "$1" -name "*$2*" -print0 | ## No need for a temp file, just pipe the output directly ## to the while loop while IFS= read -r -d '' lig do echo "$lig nombre de ligne: $(wc -l < "$lig")" done 

Из help read : «Прочитайте строку со стандартного ввода и разделите ее на поля». Другими словами, он читает целую строку и пытается разбить ее на 3 разные части и сохранить каждую из этих частей в 3 переменных, которые вы назвали. Обратите внимание: если в строке есть только одна часть, две другие переменные не будут установлены. Вы не используете $ там, потому что вы не хотите передавать текущее значение переменной, а вместо этого имя переменной, чтобы она знала, что она должна установить ее значение.

  • Как удалить лишний «мусор» из этого файла журнала?
  • Конкатенация двух полей из двух файлов
  • Shell Scripting: Сравнивая что-то с ничем?
  • printf в моем выпуске теперь
  • Я неправильно использую цикл while?
  • Получение ошибки вывода с помощью команды head в сценарии оболочки
  • Команда Killall?
  • Unix-скрипты - для команды do с &
  • Count nul разделили элементы в файле
  • Начальный сценарий
  • Как обрабатывать подкоманду в сценарии оболочки?
  • Interesting Posts

    Запустите команду в интерактивной оболочке с помощью ssh после поиска .bashrc

    Конкретный способ вывода в файл, если задан аргумент, в stdout в противном случае

    acpi_listen возвращает другой результат в Ubuntu, чем Arch Linux

    ksh loop: "для dir in find .. do" не работает, в отличие от "для dir in ls .. do"

    как сделать firefox прочитанным stdin

    терминал зависает после запуска сервера red5

    Что не так с моей командой копирования?

    Дисплей не поддерживает DPMS После обновления GNOME Wayland

    Как сохранить вывод R stargazer (data.frame) в .tex документе?

    Разрешения группы неэффективны, разрешение все еще запрещено

    Как выбрать интегрированную графическую карту через NVIDIA?

    Как получить доступ к звуковому устройству с помощью современных библиотек?

    Постоянное переключение на Linux

    Как я могу остановить запуск inotifywait из другого скрипта?

    Автоматическое и надежное резервное копирование данных

    Linux и Unix - лучшая ОС в мире.