awk 不在 csv 的最后一列中进行替换
awk not making substitutions in last column of csv
我需要处理大型 .tsv
的列,如果列名与多个字符串中的任何一个匹配,我就替换它,如果找不到匹配项,则将其标记为错误。下面是我所拥有的简化版本,它在这里有效。
制表符分隔输入示例 test.tsv
:
Col1 Col2 Col3 Col4
A B C Foo
D E F Bar
G H I Baz
脚本:
#!/bin/bash
set -eu
shopt -s failglob
awk 'BEGIN {FS=OFS="\t"} \
{if (NR==1) \
{for (i = 1 ; i <= NF ; i++) \
if ($i == "Col1") { $i = "NewCol1" } \
else if ( $i == "Col2") { $i = "NewCol2" } \
else if ( $i == "Col4") { $i = "NewCol4" } \
else { $i = "Error: "$i } \
} print \
}' test.tsv
制表符分隔的输出:
NewCol1 NewCol2 Error: Col3 NewCol4
A B C Foo
D E F Bar
G H I Baz
但是在我的真实过程中Col4
并没有被成功处理。相反,它被标记为错误。如果我使用 LibreOffice Calc 打开文件并再次保存,则不会出现此问题,仍为 .tsv
。这让我觉得这可能是一个行结束格式问题,但我已经使用 vim 检查输入文件中的结尾,它们始终是 \n
。我在这里错过了什么?
显然您输入的行以 ^M
或 \r
结尾。您可以在 RS
中将此 awk
与自定义正则表达式一起使用(这需要 GNU awk
):
awk -v RS='\r?\n' '...' file
-v RS='\r?\n'
将 RS
或记录分隔符设置为 可选 \r
后跟 \n
,从而允许它匹配行以 \n
或 \r\n
.
结尾
我需要处理大型 .tsv
的列,如果列名与多个字符串中的任何一个匹配,我就替换它,如果找不到匹配项,则将其标记为错误。下面是我所拥有的简化版本,它在这里有效。
制表符分隔输入示例 test.tsv
:
Col1 Col2 Col3 Col4
A B C Foo
D E F Bar
G H I Baz
脚本:
#!/bin/bash
set -eu
shopt -s failglob
awk 'BEGIN {FS=OFS="\t"} \
{if (NR==1) \
{for (i = 1 ; i <= NF ; i++) \
if ($i == "Col1") { $i = "NewCol1" } \
else if ( $i == "Col2") { $i = "NewCol2" } \
else if ( $i == "Col4") { $i = "NewCol4" } \
else { $i = "Error: "$i } \
} print \
}' test.tsv
制表符分隔的输出:
NewCol1 NewCol2 Error: Col3 NewCol4
A B C Foo
D E F Bar
G H I Baz
但是在我的真实过程中Col4
并没有被成功处理。相反,它被标记为错误。如果我使用 LibreOffice Calc 打开文件并再次保存,则不会出现此问题,仍为 .tsv
。这让我觉得这可能是一个行结束格式问题,但我已经使用 vim 检查输入文件中的结尾,它们始终是 \n
。我在这里错过了什么?
显然您输入的行以 ^M
或 \r
结尾。您可以在 RS
中将此 awk
与自定义正则表达式一起使用(这需要 GNU awk
):
awk -v RS='\r?\n' '...' file
-v RS='\r?\n'
将 RS
或记录分隔符设置为 可选 \r
后跟 \n
,从而允许它匹配行以 \n
或 \r\n
.