在 while read 循环中使用 read 命令时出现问题

在 while read 循环中使用 read 命令时出现问题

我试图设置一个 while read 循环行来逐行读取输入文本文件,并将两个字符串作为文本文件中每一行的变量传递。

    while IFS= read -r line
do
    # Read and pass two path strings as variables.
    read path1 path2
    echo "$path1"
    echo "$path2"
done < "$1"

read path1 path2它似乎在为每个当前行中的字符串分配变量之前处理文本文件中的下一行。

在转到下一行之前,如何在每一行上将字符串作为变量传递?

答案1

read循环体内的第二个在这里是不正确的。read作为 while 循环的一部分,它实际上比您的第一次调用提前一行。因此,根据您的要求,只需将这些变量作为第一个变量的一部分读取read

while read -r path1 path2; do
    echo "$path1"
    echo "$path2"
done < "$1"

正如您在此处看到的,IFS=在读取两个变量时,设置也是不正确的,因为重置字段分隔符只会拾取整个行。通过使用其默认值(空格、制表符和换行符等空白字符),读取两个变量会将每行的值存储在空格分隔的列表中。这样我们就可以有 n 列分隔行并使用 n 个变量来读取。

现在这些值在这些变量中可用,您可以根据需要将其传递给其他命令。

让我们看看这对于示例输入文件是如何工作的

foo bar
foo1 bar1
foo2 bar2

-x使用set在调试模式下运行第一个脚本

$ bash -x script.sh
+ read -r path1 path2
+ echo 1
1
+ echo 2
2
+ read -r path1 path2
+ echo 3
3
+ echo 4
4
+ read -r path1 path2
+ echo abc
abc
+ echo def
def
+ read -r path1 path2

答案2

如果你想让线路完好无损从中提取值,您可以使用这里的字符串:

while IFS= read -r line; do
    read -r path1 path1 <<< "$line"
    echo "$line"
    echo "$path1:$path2"
done < file

事实上,并非所有 shell 都支持here-string。但是,所有 POSIX 类型的 shell 都支持此处文档。

while IFS= read -r line; do
    read -r path1 path1 << _LINE_
$line
_LINE_
    echo "$line"
    echo "$path1:$path2"
done < file

答案3

通过将文件重定向到for循环中,整个循环中从标准输入的所有读取都将从同一文件中读取。这意味着read循环中的两个命令将从您作为第一个参数传递给脚本的任何文件中读取替代行。

我有点不清楚你想要数据path1从哪里来path2。如果要从文件中读取这些内容,只需在循环头中执行即可:

while read -r path1 path2; do
    printf 'path1 = "%s"\n' "$path1"
    printf 'path2 = "%s"\n' "$path2"
done <"somefile"

该答案的其余部分假设您想从文件中读取某些内容,然后在循环中从终端读取某些内容。

要使read循环体从终端读取:

exec 3<"somefile"

while IFS= read -r words <&3; do
   read -r word1 word2 junk
   printf 'Got words = "%s"\n' "$words"
   printf 'Got word1 = "%s"\n' "$word1"
   printf 'Got word2 = "%s"\n' "$word2"
done

这使得第一个的输入read来自文件somefile,而第二个的标准输入流read将从终端(或脚本的标准输入流来自的任何地方)读取。

相关内容