从标准输入 Bash 中逐行读取

问题描述 投票:0回答:2

我正在学习 语言,考试曲目如下:

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

我的问题有两个:

  1. 如何从 Bash 中的标准输入中逐行读取?到目前为止,我使用

    "read string"
    ,但我不认为它一次读取一行。

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

    hello
    world
    )。我如何将这两行赋予 bash 脚本?

bash unix stdin
2个回答
38
投票
  1. 如何从 Bash 中的标准输入中逐行读取?直到现在我 使用“读取字符串”,但我不认为它一次读取一行。

read
的原型是:

read [options] name[s ...]

read
将读取
line
输入到
name name1 name2 ...
,根据 内部字段分隔符 (
IFS
) 的内容分割行。
IFS
的默认值为
' \t\n'
(即
space
tab
newline
)。如果您只向
read
提供单个变量,您会将整行读入该变量(除非您使用
-d
选项为
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
来更改分词的方式。仔细看看 anubhava 提供的答案作为示例。您可以自由指定任何您想要分割单词的字符。 (有助于解析
csv
文件以设置
IFS=$',\n'
并将单词拆分为
','
而不是空格)

为了确保将整行读入变量,您可以仅向

read
提供单个变量并设置
IFS='$\n'
以确保仅在
newline
上进行分词。 (注意: 将更改作为
while
循环的一部分提供,会限制
IFS
对该循环范围的更改。例如:

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

将确保

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


10
投票

你可以这样做:

# 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
© www.soinside.com 2019 - 2024. All rights reserved.