Regex 使用sed更改CSV分隔符

Regex 使用sed更改CSV分隔符,regex,sed,Regex,Sed,我有一个CSV文件,看起来像: 1,3,"3,5",4,"5,5" 现在我想用sed将所有的“,”不在引号内改为“;”,所以看起来像这样: 1;3;"3,5";5;"5,5" echo '1,3,"3,5",4,"5,5"' | sed -r 's|("[^"]*),([^"]*")|\1\x1\2|g;s|,|;|g;s|\x1|,|g' 但我找不到一种有效的模式。您可以尝试以下方式: 1;3;"3,5";5;"5,5" echo '1,3,"3,5",4,"5,5"' | sed -

我有一个CSV文件,看起来像:

1,3,"3,5",4,"5,5"
现在我想用sed将所有的“,”不在引号内改为“;”,所以看起来像这样:

1;3;"3,5";5;"5,5"
echo '1,3,"3,5",4,"5,5"' | sed -r 's|("[^"]*),([^"]*")|\1\x1\2|g;s|,|;|g;s|\x1|,|g'

但我找不到一种有效的模式。

您可以尝试以下方式:

1;3;"3,5";5;"5,5"
echo '1,3,"3,5",4,"5,5"' | sed -r 's|("[^"]*),([^"]*")|\1\x1\2|g;s|,|;|g;s|\x1|,|g'

它将引号中的所有逗号替换为\x1字符,然后将所有剩余的逗号替换为分号,然后将\x1字符替换回逗号。这可能会起作用,因为文件的格式正确,文件中最初没有\x1字符,也不存在双引号中有双引号的情况,例如“a\”b)。

使用
gawk

gawk '{$1=$1}1' FPAT="([^,]+)|(\"[^\"]+\")" OFS=';' filename
测试:
如果只需要数字,则以下表达式将起作用

sed -e 's/,/;/g' -e 's/\("[0-9][0-9]*\);\([0-9][0-9]*"\)/\1,\2/g'
e、 g

你不能仅仅用。*替换[0-9][0-9]*来保留任何内容,因为用引号表示,.*太贪婪,匹配太多。所以你必须使用[a-z0-9]*

$ echo '1,3,"3,5",4,"5,5",",6","4,",7,"a,b",c' | sed -e 's/,/;/g' -e 's/\("[a-z0-9]*\);\([a-z0-9]*"\)/\1,\2/g'
1;3;"3,5";4;"5,5";",6";"4,";7;"a,b";c

与第一个解决方案相比,它的优点是易于理解。我们只需将每个替换为;然后将引号中的每个更正为,

这可能适用于您:

echo '1,3,"3,5",4,"5,5"' | 
sed 's/\("[^",]*\),\([^"]*"\)/\1\n\2/g;y/,/;/;s/\n/,/g'
1;3;"3,5";4;"5,5"
这里有一个更长但更灵活的替代解决方案:

echo '1,3,"3,5",4,"5,5"' | 
sed 's/^/\n/;:a;s/\n\([^,"]\|"[^"]*"\)/\1\n/;ta;s/\n,/;\n/;ta;s/\n//'
1;3;"3,5";4;"5,5"

这是最近才在这里讨论过的。搜索tag=gawk/awk和CSV。这很难做到,特别是在您显示数据的情况下使用sed。祝您好运。见鬼,写一个脚本来捕捉坏情况(对
\\“
的误报可能比丢失
\”
要好)。我可以提出同样的建议,但这不是作者想要的:)在CSV中,引号中的双引号应该写为
“foo”“bar”
。我知道,因为我在中查找了它。(如果生成数据的人从未查看过规范,这并没有帮助。)我一直在@Jaypal上等待你的回答,谢谢,我已经提交了一个解决方案。还添加了一个替代方案:)