如何使用sed

时间:2015-06-19 20:20:23

标签: regex bash csv sed

我到处都看了,但找不到答案。我之前使用过sed,所以我对语法很熟悉 - 不过这个让我很难过。

我想删除除前3个实例和特定字符的最后一个实例之外的所有实例。这是一个具体的例子:

input.csv:

"first", "some text "quote" blaw blaw", 1
"second", "some more text "another quote" blaw blaw", 3

我想删除除前三个和最后一个之外的所有引号(“),以便它看起来像这样:

output.csv:

"first", "some text quote blaw blaw", 1
"second", "some more text another quote blaw blaw", 3

任何指针?感谢。

3 个答案:

答案 0 :(得分:2)

使用awk,使用双引号作为字段分隔符:

awk -F\" -v OFS=\" '{
   text=""
   for (i=4; i<NF; i++) text = text $i
   print $1,$2, $3, text, $NF
}' <<END
"first", "some text "quote" blaw blaw", 1
"second", "some more text "another quote" blaw blaw", 3
END
"first", "some text quote blaw blaw", 1
"second", "some more text another quote blaw blaw", 3

另一方面,如果你想修复破损的CSV,那么内部报价应加倍:

awk -F '[[:blank:]]*,[[:blank:]]*' -v OFS=, '{
    for (i=1; i<=NF; i++) {
        if ($i ~ /^".*"$/) {
            newtext = substr($i, 2, length($i)-2)
            gsub(/"/, "\"\"", newtext)
            $i = "\"" newtext "\""
        }
    }
    print
}' data
"first","some text ""quote"" blaw blaw",1
"second","some more text ""another quote"" blaw blaw",3

答案 1 :(得分:1)

$ sed -r ':a; s/([^"]*"[^"]*"[^"]*")([^"]*)"([^"]*")/\1\2\3/; ta' input.csv
"first", "some text quote blaw blaw", 1
"second", "some more text another quote blaw blaw", 3

如何运作

代码通过查找前五个引号来工作。它删除了第四个。循环重复此过程,直到只剩下四个引号。

  • :a

    这定义了标签a

  • s/([^"]*"[^"]*"[^"]*")([^"]*)"([^"]*")/\1\2\3/

    这会查找前三个引号以及它们在组1之前的所有文本。它会将下一组非引号字符作为组2查找。它会查找以下双引号。然后它会查找非引号字符,然后查找第五个引号作为第3组。它将三个组替换为第三个引号。

    让我们更明确地解决这个问题:

    • ([^"]*"[^"]*"[^"]*")

      这将查找前三个引号以及它们之前的所有文本。这将保存为组1。

    • ([^"]*)

      这会查找下一组非引号字符。它们被保存为第2组。

    • "

      这符合该行的第四个引用。

    • ([^"]*")

      这匹配下一组非引号字符,后跟第五行引号。它保存为第3组。

    替换文本为\1\2\3,其效果是删除找到的五个引号的第四个引号。

  • ta

    如果进行了替换,则会循环回标签a。如果没有,那么我们就完成了这一行。

BSD或Mac OSX

尝试:

sed -E -e ':a' -e 's/([^"]*"[^"]*"[^"]*")([^"]*)"([^"]*")/\1\2\3/' -e 'ta' input.csv

答案 2 :(得分:0)

这可能适合你(GNU sed):

sed 's/^\(.*\)"/\1\n/;/s/"//4g;s/\n/"/' file

这会将最后一个"替换为唯一字符(\n),然后从第四个开始删除所有",最后用{{替换唯一字符1}}。