我到处都看了,但找不到答案。我之前使用过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
任何指针?感谢。
答案 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
。如果没有,那么我们就完成了这一行。
尝试:
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}}。