使用bash脚本和sed修复报价转义

时间:2012-10-05 11:41:39

标签: bash sed

我有一个处理一些CSV的bash文件。某些输入CSV格式不正确,所以我想用sed修复它们。报价会像\"一样转义,而不是"",所以我打电话给sed来改变它。在命令行中,这非常有效:

sed -i 's/\\"/""/gi' input.csv

但是在bash脚本中,这似乎什么都不做。我想这与引号和转义序列有关,但解决方案是什么?

2 个答案:

答案 0 :(得分:5)

你需要转义转义字符\才能使其工作:

$ echo 'bla;\"bli bli\";otherbla' | sed -e 's/\\\"/""/g'
bla;""bli bli"";otherbla

对于bash脚本,您需要确保在将文件传递给sed时正确引用从CSV文件中读取的行。您能否提供CSV文件的示例以及您如何从文件中读取文件?

使用cat file | while read,以下是问题的示例:

$ cat test.csv
bla;\"bli bli\";otherbla
ble;""bli bli"";otherbla
bli;\"blo\";otherbla

$ cat test.sh
#!/bin/bash

cat test.csv | while read line;
do echo "$line" | sed -e 's/\\\"/""/g'
done

$ ./test.sh
bla;"bli bli";otherbla
ble;""bli bli"";otherbla
bli;"blo";otherbla

一种解决方案是不在脚本中使用echo,而是直接在文件上使用sed并将生成的csv存储在新文件中:

$ sed -e 's/\\\"/""/ig' test.csv > test-tmp.csv
$ cat test-tmp.csv
bla;""bli bli"";otherbla
ble;""bli bli"";otherbla
bli;""blo"";otherbla

然后,正如评论所指出的,为了避免被\整理的引用字段的错误替换和错误替换,我们可以使用2个sed表达式,并包括字段分隔符以确保我们只替换 \"在字段分隔符之前或之后(在我的示例中,字段分隔符为;)但是这个字符不考虑单引号为\的字段字段中的字符,例如blo行:

$ cat test.csv
bla;\"bli bli\";otherbla
ble;""bli bli"";otherbla
bli;\"blo\";otherbla
blo;"bli bli\";otherbla
blu;""bli bli\"";otherbla

$ sed -e 's/;\\\"/;""/ig' -e 's/\\\";/"";/ig' test.csv
bla;""bli bli"";otherbla
ble;""bli bli"";otherbla
bli;""blo"";otherbla
blo;"bli bli"";otherbla
blu;""bli bli\"";otherbla

如果你有几个sed命令,你可以把它放在一个脚本中,它的工作原理相同:

$ cat s.sed 
s/\\\"/""/g

使用它:

$ echo 'bla;\"bli bli\";otherbla' | sed -f s.sed 
bla;""bli bli"";otherbla

sed -f s.sed test.csv > test-tmp.csv

答案 1 :(得分:3)

您是否考虑过其中一个字段合法地以\字符结尾的情况? CSV文件中的引用表示将以反斜杠后跟引号结束;诸如你和托马斯的解决方案将破坏它。

这就是为什么sed是使用引用的csv的错误工具;有些问题只能用适当的语言(awk,Perl或其他)递归解决