带切割的 Bash Loop

带切割的 Bash Loop

我有一个文件(称为文件),其中有许多行,每行之间都有一个空格,如下所示:

abc 123
def 456
ghi 789

我需要循环遍历并抓取每个字段来稍微处理一下文本。我一直尝试这样做:

for i in `cat file`

do

var1=`echo ${i} | cut -d" " -f1`
var2=`echo ${i} | cut -d" " -f2`

echo "var1: ${var1} and var2: ${var2}"

done

以下是我得到的输出:

var1: abc and var2: abc
var1: 123 and var2: 123
var1: def and var2: def
var1: 456 and var2: 456
var1: ghi and var2: ghi
var1: 789 and var2: 789

为了清楚起见,预期输出将是:

var1: abc and var2: 123
var1: def and var2: 456
var1: ghi and var2: 789

不确定为什么这不起作用。我该怎么做才能获得预期的输出?

答案1

#!/bin/bash
input="/root/test.txt"

 while IFS=' ' read -r f1 f2
 do
     printf 'VAR1: %s VAR2: %s\n' "$f1" "$f2"
 done <"$input"

答案2

@ddiser 有一个我想象中的可行的解决方案,但没有解释原因,我认为这就是问题所在。

答案是“cat file”的输出 - 即由空格和换行符分隔的字符串列表。

当 for 语句看到结果时,它使用空格字符作为分隔符 - 它是否像您期望的那样处理空格来处理换行符。为了证明这一点,您可以修改文件以使用空格以外的字符(例如逗号或竖线),然后更改 cut 命令上的分隔符,这样就可以了。如果您使用 cat file|tr ' ' '|' " 而不是“cat file”,您甚至可以使用相同的文件格式(这并不是说这是 cat 的适当用法,但它应该有效)

答案3

我尝试结合之前贡献者的意见,并使用您的一些格式。此外,我还对您的代码进行了现代化改造,您也应该在编码时更广泛地考虑这一点。如果您有任何问题,请告诉我。

while IFS= read -r line ; do 
    var1="$( printf '%b' "${line}" | cut -d " " -f1 )" 
    var2="$( printf '%b' "${line}" | cut -d " " -f2 )" 
    printf '%s\n' "var1:  ${var1} and var2:  ${var2}" 
done < /path/to/your/file.txt 

这会起作用,因为 read 将文件的每一行都发送到循环。您的版本不会起作用,因为 cat 会先将文件发送到循环而不先对其进行划分。

无论如何,正如您可能猜到的那样,还有许多其他方法可以完成同一件事,因此您真的可以从 bash 中的许多不同工具中进行选择来制定解决方案。

相关内容