我有一个如下所示的文件:
14757,file_one
14756,file_two
14755,file_three
Run Code Online (Sandbox Code Playgroud)
我想循环每一行并通过单独的变量引用元组组件。例如,当迭代第一行时,$1将是14757并且$2将具有值file_one。
我尝试通过以下方式实现这一目标:
for i in $(cat files.txt); do IFS=","; set -- $i; echo $1 and $2; done
Run Code Online (Sandbox Code Playgroud)
然而,它循环遍历每个单词,结果不是我所期望的:
14757 and
file_one
14756 and
file_two
14755 and
file_three and
Run Code Online (Sandbox Code Playgroud)
这就是我要的:
14757 and file_one
14756 and file_two
14755 and file_three
Run Code Online (Sandbox Code Playgroud)
我尝试调整问题Loop over tuples in Bash中发布的解决方案,但没有成功。
如果那是你觉得你需要的,那么
$: while IFS=$'",\n' read -a line; do set -- "${line[@]}"; shift; echo $1 and $2; done <tmp
14757 and file_one
14756 and file_two
14755 and file_three
Run Code Online (Sandbox Code Playgroud)
我使用引号和逗号作为分隔符,这会在单元格 0 中创建一个前导空字段,因此我将shift其关闭。
...但是除非有令人信服的理由,否则就使用数组。
$: while IFS=$'",\n' read -a fields; do echo "${fields[1]} and ${fields[2]}"; done <tmp
14757 and file_one
14756 and file_two
14755 and file_three
Run Code Online (Sandbox Code Playgroud)
awk如果结果集非常大,效率会更高,而且速度会更快 -
$: awk -F'[",]' '{print $2" and "$3}' tmp
14757 and file_one
14756 and file_two
14755 and file_three
Run Code Online (Sandbox Code Playgroud)
甚至sed-
$: sed 's/^"//; s/"$//; s/,/ and /;' tmp
14757 and file_one
14756 and file_two
14755 and file_three
Run Code Online (Sandbox Code Playgroud)
这个有点更直接和机械,但如果你阅读正则表达式,它很容易理解:修剪前导引号,修剪尾随引号,转换逗号。我本来可以使用s/"//g,但我怀疑这两个锚定替换比扫描整个字符串更快,因为我知道引号在哪里。这在这里可能并不重要,但值得一提的是,当您处理多 GB 文件并且希望节省一点时间时。
如果您确实通过 a管道传输数据tr并删除引号,那么所有这些都会更简单,因为它们不再需要处理该问题,并且您不会忽略第一个空字段。
$: while IFS=, read -a line; do set -- "${line[@]}"; echo $1 and $2; done <tmp
14757 and file_one
14756 and file_two
14755 and file_three
$: while IFS=, read -a fields; do echo "${fields[0]} and ${fields[1]}"; done <tmp
14757 and file_one
14756 and file_two
14755 and file_three
$: awk -F, '{print $1 " and " $2}' tmp
14757 and file_one
14756 and file_two
14755 and file_three
$: sed 's/,/ and /;' tmp
14757 and file_one
14756 and file_two
14755 and file_three
Run Code Online (Sandbox Code Playgroud)
循环的一种变体while/read:
$ while IFS=, read -r arg1 arg2; do echo "${arg1} and ${arg2}"; done < files.txt
14757 and file_one
14756 and file_two
14755 and file_three
Run Code Online (Sandbox Code Playgroud)