Читать построчно со стандартного ввода Баш

Я учусь Баш язык и экзамен трек говорит так:

Он должен читать один вход (от стандартного входа) за раз (каждая запись является строкой, а затем заканчивается новой строкой).

мои вопросы два:

  1. как читать строку за строкой из стандартного ввода в Bash? До сих пор я использовал "read string" но я не думаю, что он читает строку за раз.

  2. Я не знаю, если это глупый вопрос, но после создания скрипта, как я могу дать больше строк скрипту в качестве ввода (чтение из стандартного ввода, конечно). Например,stdin вставить две строки (hello и world). Как я могу дать скрипт эти две линии?

2 ответов


1) Как читать строку за строкой из стандартного ввода в Bash? До сих пор я используется "читать строку", но я не думаю, что она читает строку за раз.

прототип read - это:

read [options] name[s ...]

read прочитал line вход в name name1 name2 ... разделение строки на основе содержимого Разделитель Внутреннего Поля (IFS). Значение по умолчанию для IFS is ' \t\n' (то есть space tab newline). Если вы предоставьте только одну переменную read, вы прочитаете всю строку в этой переменной (если вы не установили новый разделитель с до read). Если вы предоставляете более одной переменной (например,read -r name name1) разбиение будет происходить на основе текущего значения IFS. Значение, если вы предоставляете строку hello world в:

read -r name

name="hello world". С другой стороны, если вы предоставите ту же строку:

read -r name name1

name="hello", name1="world". Что, если ты ... есть лишние слова в строке, но только 2 переменные? Скажите, что ваша строка теперь "hello big wide world", что случается с:

read -r name name1

name="hello", name1="big wide world". Слова в string назначаются вашим переменным по порядку, и если переменных недостаточно для хранения каждого слова в строке, последняя переменная будет содержать все оставшиеся слова в строке, ранее не назначенной.

вы изменяете, как происходит разделение слов, изменяя IFS. Внимательно посмотреть на ответ Анубхава, например. Вы можете указать любой символ, на который вы хотите разделить слова. (полезно сказать разбор установить IFS=$',\n' и разделите слова на ',' вместо пробела)

чтобы убедиться, что Вы читаете всю строку в переменную, вы можете предоставить только одну переменную read и set IFS='$\n' для обеспечения разделения слов происходит только на newline. (Примечание: предоставление изменения в составе while петля ограничивает IFS изменение объема этого цикла. Например:

while IFS='$\n' read -r line; do
    # do whatever with line
done

будет гарантировать, что каждая линия на stdin будет читаться в line при сохранении нормального разделения слов вне цикла. Внутри цикла вы можете добавить каждую строку в массив, как показывает Анубхава в своем ответе. (чтобы сохранить все пробелы IFS= используется)


вы можете сделать что-то вроде этого:

# array to hold all lines read
lines=()

# read all lines in lines array
while IFS= read -r line; do
    lines+=( "$line" )
done < file

# read 3 more lines from stdin
for ((i=0; i<3; i++)); do
   read -rp "Enter a line: " line
   lines+=( "$line" )
done