替换文件中的引号

替换文件中的引号

我有大量以分号分隔的大型数据文件。所有字符串字段都用双引号括起来。在某些文件中,字符串字段中有多余的引号,这会弄乱后续导入数据进行分析的过程(我正在导入 Stata)。

此代码允许我使用 gnu-awk 查看有问题的引号:

echo '"This";"is";1;"line" of" data";""with";"extra quotes""' | awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")"}; {for ( i=1 ; i<=NF ; i++ ) if ($i ~ /^"(.*".*)+"$/) {print NR, $i}}'
1 "line" of" data"
1 ""with"
1 "extra quotes""

但我不知道如何替换它们。

我原本想手动进行替换,但结果发现有些文件中有几百个匹配项。我知道 awk 的 -sub-、-gsub- 和 -match- 函数,但我不知道如何针对这个特定问题设计搜索和替换。

在上面的例子中,相应的字段应该是,,,,,,,"This"即:所有分号都是分隔符,并且除了最外面的引号之外的所有引号都应该被删除"is"1"line of data""with""extra quotes"

我是否应该使用 -sed-,或者 -awk- 是正确的工具?希望你能帮助我!

谢谢,

马蒂斯

答案1

GNU awk使用and 的一种方式FPAT

awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")" } { for (i=1; i<=NF; i++) if (substr($i,0,1) == "\"" && substr($i,length($i),1) == "\"") { gsub(/"/, "", $i); printf "\"%s\"\n", $i } else { gsub(/"/, "", $i); print $i } }'

测试:

echo '"This";"is";1;"line" of" data";""with";"extra quotes""' | awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")" } { for (i=1; i<=NF; i++) if (substr($i,0,1) == "\"" && substr($i,length($i),1) == "\"") { gsub(/"/, "", $i); printf "\"%s\"\n", $i } else { gsub(/"/, "", $i); print $i } }'

结果:

"This"
"is"
1
"line of data"
"with"
"extra quotes"

一种方法是使用GNU awk和:FPATGNU sed

sed -e '/^".*"$/ { s/"//g; s/.*/"&"/ }' -e '/^".*"$/!s/"//g'

测试:

echo '"This";"is";1;"line" of" data";""with";"extra quotes""' | awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")" } { for (i=1; i<=NF; i++) print $i }' | sed -e '/^".*"$/ { s/"//g; s/.*/"&"/ }' -e '/^".*"$/!s/"//g'

结果:

"This"
"is"
1
"line of data"
"with"
"extra quotes"

答案2

我宁愿使用 coreutils 和 sed (GNU 版本):

<<< '"This";"is";1;"line" of" data";""with";"extra quotes""' \
| tr ';' '\n' | sed -r 's/(.)"(.)/\1\2/g' | tr '\n' ';'

输出:

"This";"is";1;"line of data";"with";"extra quotes";

它留下一个额外的分号,并删除换行符,head -c -1在第二个分号之前插入并附tr加以; echo修复:

tr ';' '\n' | sed -r 's/(.)"(.)/\1\2/g' | head -c -1 | tr '\n' ';'; echo

输出:

"This";"is";1;"line of data";"with";"extra quotes"

答案3

我自己的解决方案是仅使用sed,去掉所有不与分隔符或数字字段并列的分号(该awk命令只是为了说明清楚):

echo '"This";"is";1;"line" of" data";""without";"extra quotes""' | sed -E 's/([^;])"+([^;])/\1\2/g' | awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")"}; {for ( i=1 ; i<=NF ; i++ ) print $i}'
"This"
"is"
1
"line of data"
"without"
"extra quotes"

我认为它更快,因为它在整行上工作,而不是按字段分割行。

相关内容