试图从双引号内删除某些字符,但保留它们作为分隔符

时间:2013-12-25 11:09:12

标签: bash sed awk

从引用的字符串中删除字符(分号)但保留它们的分隔符

我如何获得sed等。

我的输入文件

"1234";"ABCDE;";"9999"
"2344;";"PQRST"; "3456;"

我的outpuft文件需要清理,看起来像

"1234";"ABCDE";"9999"
"2344";"PQRST";"3456"

如上所示,分号需要保留为分隔符,但需要从引用的部分中删除。有人能让我知道吗?感谢。

我实际上正在做一些hive编程,我的hive脚本已经准备好并且运行成功(在较小的示例数据集上测试)。现在这些相同的脚本给了我错误,因为这些新的大数据集不干净,因此试图清理它们(并且沿途学习sed等)。

的问候, 拉胡

4 个答案:

答案 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"

如果由于某种原因您无法轻松升级发行版,请使用PerlCPAN模块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