如何在csv文件的特定列中用AWK替换多个字符?

如何在csv文件的特定列中用AWK替换多个字符?,csv,awk,Csv,Awk,我有一个csv文件,其中包含数千行 我需要替换特定列中的一些字符 &acirc ; ---> a &amp ; ---> & &eacute ; ---> é 我试过使用这个命令,但不起作用 awk 'BEGIN{FS=OFS=";"} {for (i=3;i<=NF;i++) gsub("/\&amp\;/","\&",$3); gsub("/\&middot\;/", " ",$3); gsub("/\&

我有一个csv文件,其中包含数千行

我需要替换特定列中的一些字符

&acirc ; ---> a
&amp ; ---> &
&eacute ; ---> é
我试过使用这个命令,但不起作用

awk 'BEGIN{FS=OFS=";"} {for (i=3;i<=NF;i++) gsub("/\&amp\;/","\&",$3); gsub("/\&middot\;/", " ",$3); gsub("/\&acirc\;/", "a",$3); gsub("/\&eacute\;/", "e",$3); gsub(/\#/, " ",$3)}' file.csv
预期产出:

32602;1;"Wet & Dry 5029";2663,2662

那么,您想用
awk
解析CSV文件并只修改列的子集吗

首先,解析CSV字段不像在分隔符(
,或者在您的情况下是
)上拆分那样简单,因为在引用值时必须避免拆分。这方面的
awk
方法在中给出,如果您使用GNU
awk
,最优雅的方法是:

(对于其他
awk
s和一些特殊情况,请参见引用的答案。)

现在回到你的节目。
gsub
参数的正确语法是
/pattern/
“pattern”
,但不是两者都是(例如
“/pattern/”

这意味着您必须按如下方式更换:

gsub("/\&amp\;/","\&",$3)     -->  gsub(/&amp;/, "\\&", $3)
gsub("/\&middot\;/", " ",$3)  -->  gsub(/&middot;/, " ", $3)
gsub("/\&acirc\;/", "a",$3)   -->  gsub(/&acirc;/, "a", $3)
gsub("/\&eacute\;/", "e",$3)  -->  gsub(/&eacute;/, "e", $3)
还要注意,在ERE regexp部分中,
不必转义,但在替换字符串中,
&
需要转义(使用同样需要转义的
\

此外,要仅修改列
$3
,不需要
for
循环。但是,如果确实要修改以
$3
开始并以最后一个
$NF
结束的列范围,则需要在每个
gsub
调用中使用
$i
,而不是
$3

已修复,您的
awk
程序如下所示:

awk -v FPAT='[^;]*|"[^"]+"' -v OFS=';' '{
    for (i=3; i<=NF; i++) {
        gsub(/&amp;/, "\\&", $i)
        gsub(/&middot;/, " ", $i)
        gsub(/&acirc;/, "a", $i)
        gsub(/&eacute;/, "e", $i)
        gsub(/#/, " ", $i)
    }
    print
 }' file.csv

在注释中进行额外的故障排除之后,问题的解决方案似乎不是替换某些特定列中的HTML实体,而是替换整个文件中的HTML实体,因为您的CSV文件似乎格式不正确,因此后续处理器无法解析它(可能是由于未加引号的
s)

您可以使用简单的
sed
命令替换指定的所有HTML实体,如:

sed -e 's/&amp;/\&/g' -e 's/&middot;/ /g' -e 's/&acirc;/a/g' -e 's/&eacute;/e/g' -e 's/#/ /g' file

从您的
文件.csv中发布几行输入行欢迎来到stack overflow,请在代码标签中发布示例输入和预期输出(根据论坛规则)。谢谢您的回答,但还不起作用。这是我的csv文件的一个示例行-->32602;1.“干湿5029”;26632662当我申请csv文件时,我仍然拥有&;它在&中没有被替换。知道为什么吗?现在看看,问题是在
上拆分,因此您确实需要正确的CSV解析。感谢您提供非常清晰的信息。但实际上,我仍然有一个问题。csv编码不好,这就是为什么我想用awk替换这些包含特殊字符“;”和“#”的字符,因为这会在我将csv导入数据库时引发问题。当我应用新代码时,我现在在第3列a“;”中有很多行,而不是空格。在这种情况下,我建议您尝试使用一个简单的
sed-e/&/\&/g'-e's/·;//g'-e's/â/a/g'-e's/é/e/g'-e's/#//g'file>newfile
而不是使用
awk
?它将替换这些序列,无论它们在文件中的什么位置,但似乎对您也适用。在我的答案中添加了最终解决方案。
awk -v FPAT='[^;]*|"[^"]+"' -v OFS=';' '{
    for (i=3; i<=NF; i++) {
        gsub(/&amp;/, "\\&", $i)
        gsub(/&middot;/, " ", $i)
        gsub(/&acirc;/, "a", $i)
        gsub(/&eacute;/, "e", $i)
        gsub(/#/, " ", $i)
    }
    print
 }' file.csv
$ echo '32602;1;"Wet &amp; Dry 5029";2663,2662' | awk -v FPAT='[^;]*|"[^"]+"' -v OFS=';' '{for (i=3;i<=NF;i++) {gsub(/&amp;/,"\\&",$i); gsub(/&middot;/," ",$i); gsub(/&acirc;/,"a",$i); gsub(/&eacute;/,"e",$i); gsub(/#/," ",$i)}; print}'
32602;1;"Wet & Dry 5029";2663,2662
sed -e 's/&amp;/\&/g' -e 's/&middot;/ /g' -e 's/&acirc;/a/g' -e 's/&eacute;/e/g' -e 's/#/ /g' file