从引用的字符串中删除字符(分号)但保留它们的分隔符
我如何获得sed等。
我的输入文件
"1234";"ABCDE;";"9999"
"2344;";"PQRST"; "3456;"
我的outpuft文件需要清理,看起来像
"1234";"ABCDE";"9999"
"2344";"PQRST";"3456"
如上所示,分号需要保留为分隔符,但需要从引用的部分中删除。有人能让我知道吗?感谢。
我实际上正在做一些hive编程,我的hive脚本已经准备好并且运行成功(在较小的示例数据集上测试)。现在这些相同的脚本给了我错误,因为这些新的大数据集不干净,因此试图清理它们(并且沿途学习sed等)。
的问候, 拉胡
答案 0 :(得分:3)
我认为使用CSV解析器会更好。
如果您有gawk
,则可以使用FPAT
变量。尝试:
gawk 'BEGIN { FPAT="([^; ]+)|(\"[^\"]+\")"; OFS=";" } { for (i=1;i<=NF;i++) gsub(/;/, "", $i) }1' file
结果:
"1234";"ABCDE";"9999"
"2344";"PQRST";"3456"
如果由于某种原因您无法轻松升级发行版,请使用Perl和CPAN模块Text:CSV解决此问题:
perl -MText::CSV -nle '
BEGIN { $csv = Text::CSV->new({ sep_char => ";", allow_whitespace => 1 }) }
$csv->parse($_) or die;
print join(";", map { s/;//g; s/^|$/"/g; $_ } $csv->fields())
' file
结果:
"1234";"ABCDE";"9999"
"2344";"PQRST";"3456"
答案 1 :(得分:2)
假设你没有这样的记录:
";";";";";"
您可以将任务分解为以下步骤:
cat input
"1234";"ABCDE;";"9999"
"2344;";"PQRST"; "3456;"
sed -r 's@"\s*;\s*"@|@g'
"1234|ABCDE;|9999"
"2344;|PQRST|3456;"
sed -r 's@[";]@@g'
1234|ABCDE|9999
2344|PQRST|3456
sed -r 's@[^|]+@"&"@g'
"1234"|"ABCDE"|"9999"
"2344"|"PQRST"|"3456"
sed -r 's@\|@;@g'
"1234";"ABCDE";"9999"
"2344";"PQRST";"3456"
将所有命令合并为一个:
sed -r 's@"\s*;\s*"@|@g;s@[";]@@g;s@[^|]+@"&"@g;s@\|@;@g' input
答案 2 :(得分:2)
<强> SED 强>
kent$ sed -r 's/;"(;"|$)/"\1/g' f
"1234";"ABCDE";"9999"
"2344";"PQRST"; "3456"
<强> AWK 强>
单行:更长版本:
kent$ awk -F'"' -v OFS='"' '{for(i=1;i<=NF;i++)if($i~/\S+;$/){sub(/;$/,"",$i)}}7' f
"1234";"ABCDE";"9999"
"2344";"PQRST"; "3456"
oner-liner更短但在最后一行有垃圾("
):
kent$ awk -v RS='"' -v ORS='"' '/\S+;$/{sub(/;$/,"")}7' f
"1234";"ABCDE";"9999"
"2344";"PQRST"; "3456"
"
答案 3 :(得分:1)
以下是使用awk
awk '
{for (i=1;i<=NF;i++) {
if ($i=="\"") f=!f
if ($i==";" && f) $i=x
printf $i}
} {print ""}
' FS="" file
"1234";"ABCDE";"9999"
"2344";"PQRST"; "3456"
此测试;
是否在两个"
的块内,如果是,则将其删除。
要删除字段之间的空格,请使用:
awk '
{for (i=1;i<=NF;i++) {
if ($i=="\"") f=!f
if ($i==";" && f) $i=x
if ($i==" " && !f) $i=x
printf $i}
} {print ""}
' FS="" file