从标准输入 Bash 中逐行读取

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31218391/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:01:50  来源:igfitidea点击:

Read line by line from standard input Bash

bashunixstdin

提问by mario razzu

I'm studying bashlanguage and an exam track says this:

我正在学习bash语言,考试曲目是这样说的:

It should read one input (from standard input) at a time (each entry is a string and then ends with a newline).

它应该一次读取一个输入(来自标准输入)(每个条目都是一个字符串,然后以换行符结尾)。

My questions are two:

我的问题有两个:

  1. How do I read line by line from standard input in Bash? Until now I used "read string"but I do not think that it reads a line at a time.

  2. I do not know if this is a stupid question , but once created the script how can I give more lines to the script as input (read from standard input of course). For example from stdinI insert two lines (helloand world). How do I give to the bash script these two lines?

  1. 如何从 Bash 中的标准输入逐行读取?直到现在我使用过,"read string"但我认为它不会一次读取一行。

  2. 我不知道这是否是一个愚蠢的问题,但是一旦创建了脚本,我怎么能给脚本提供更多行作为输入(当然是从标准输入读取)。例如,我从标准输入插入两行(helloworld)。我如何将这两行提供给 bash 脚本?

回答by David C. Rankin

  1. How do I read line by line from standard input in Bash? Until now I used "read string" but I do not think that it reads a line at a time.
  1. 如何从 Bash 中的标准输入逐行读取?到目前为止,我使用“读取字符串”,但我认为它不会一次读取一行。

The prototype for readis:

原型为read

read [options] name[s ...]

readwill read a lineof input into name name1 name2 ...splitting the line based on the contents of the Internal Field Separator(IFS). The default for IFSis ' \t\n'(that is spacetabnewline). If you only provide a single variable to read, you will read the entire line into that variable (unless you have set a new delimiter with the -doption to read). If you provide more than one variable, (e.g. read -r name name1) word splitting will occur based on the current value of IFS. Meaning if you provide the string hello worldto:

read将读取line输入name name1 name2 ...以根据内部字段分隔符( IFS)的内容拆分行。默认IFSIS ' \t\n'(这是spacetabnewline)。如果您只向 提供一个变量read,您会将整行读入该变量(除非您设置了一个带有-d选项的新分隔符read)。如果您提供多个变量,(例如read -r name name1)将根据 的当前值进行分词IFS。这意味着如果您将字符串提供hello world给:

read -r name

name="hello world". On the other hand, if you provide the same string to:

name="hello world". 另一方面,如果您提供相同的字符串:

read -r name name1

name="hello", name1="world". What if you have excess words in the line but only 2 variables? Say your string is now "hello big wide world", what happens with:

name="hello", name1="world". 如果行中有多余的单词但只有 2 个变量怎么办?假设您的字符串是 now "hello big wide world",会发生什么:

read -r name name1

name="hello", name1="big wide world". The words in stringare assigned to your variables in order and if there are insufficient variables to hold each word in the string, the last variable will contain all remaining words in the string not previously assigned.

name="hello", name1="big wide world". instring中的单词按顺序分配给变量,如果没有足够的变量来保存字符串中的每个单词,最后一个变量将包含之前未分配的字符串中所有剩余的单词。

You change how word splitting occurs by altering IFS. Take a close look at the answer provided by anubhava for an example. You are free to specify any character you would like the words to be split on. (helpful in say parsing a csvfile to set IFS=$',\n'and have the words split on ','instead of space)

您可以通过更改IFS. 仔细看看 anubhava 提供的答案作为例子。您可以自由指定要拆分单词的任何字符。(有助于说解析csv文件以设置IFS=$',\n'并将单词拆分','而不是空格)

To ensure you read an entire line into a variable, you can provide only a single variable to readand set IFS='$\n'to ensure word splitting only occurs on newline. (Note:providing the change as part of the whileloop limits the IFSalteration to the scope of that loop. For example:

为确保您将整行读入一个变量,您可以只提供一个变量 toread和 setIFS='$\n'以确保分词只发生在 上newline。(注意:将更改作为while循环的一部分提供限制了对该循环范围的IFS更改。例如:

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

Will ensure that each line on stdinwill be read into linewhile preserving normal word-splitting outside the loop. Inside the loop you can then add each line to an array as anubhava shows in his answer. (to preserve all whitespace IFS=is used)

将确保每行都stdin被读入,line同时在循环外保留正常的分词。在循环内,您可以将每一行添加到一个数组中,如 anubhava 在他的回答中所示。(使用保留所有空格IFS=

回答by anubhava

You can do something like this:

你可以这样做:

# 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