从标准输入 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
Read line by line from standard input Bash
提问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:
我的问题有两个:
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.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 (
hello
andworld
). How do I give to the bash script these two lines?
如何从 Bash 中的标准输入逐行读取?直到现在我使用过,
"read string"
但我认为它不会一次读取一行。我不知道这是否是一个愚蠢的问题,但是一旦创建了脚本,我怎么能给脚本提供更多行作为输入(当然是从标准输入读取)。例如,我从标准输入插入两行(
hello
和world
)。我如何将这两行提供给 bash 脚本?
回答by David C. Rankin
- 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.
- 如何从 Bash 中的标准输入逐行读取?到目前为止,我使用“读取字符串”,但我认为它不会一次读取一行。
The prototype for read
is:
原型为read
:
read [options] name[s ...]
read
will read a line
of input into name name1 name2 ...
splitting the line based on the contents of the Internal Field Separator(IFS
). The default for IFS
is ' \t\n'
(that is space
tab
newline
). 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 -d
option 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 world
to:
read
将读取line
输入name name1 name2 ...
以根据内部字段分隔符( IFS
)的内容拆分行。默认IFS
IS ' \t\n'
(这是space
tab
newline
)。如果您只向 提供一个变量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 string
are 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 csv
file 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 read
and set IFS='$\n'
to ensure word splitting only occurs on newline
. (Note:providing the change as part of the while
loop limits the IFS
alteration 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 stdin
will be read into line
while 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