替换 bash 脚本中两个引号之间的所有逗号

Replace all commas between two quotes in a bash script

我需要在 bash 脚本中将两个 " 之间的所有 "," 替换为 ";"。我很接近了,但是互联网和 Whosebug 上的时间让我想到了这个:

echo ',,Lung,,"Lobular, each.|lungs, right.",false,,,,"organ, left.",,,,,' | sed -r ':a;s/(".*?),(.*?")/;/;ta'

结果:

,,Lung,,"Lobular; each.|lungs; right.";false;;;;"organ; left.",,,,,

正确的是:

,,Lung,,"Lobular; each.|lungs; right.",false,,,,"organ; left.",,,,,

不确定您要如何处理具有奇数个双引号的行(例如,双引号字符串跨越多行),但也许:

awk '!(NR%2){gsub(",",";")} 1' RS=\" ORS=\"

这只是将 " 视为记录分隔符,并且仅对奇数记录进行替换。似乎按预期工作。 (或者,更确切地说,它就像你想要的那样工作!)

正如 oguz 在评论中指出的那样,这会在末尾打印一个额外的 "。可以通过以下方式解决:

awk '!(NR%2){gsub(",",";")} {printf RFS [=11=]} {RFS="\""}' RS=\"

这有点丑陋但更正确。 (或者更确切地说,不太正确!)如果您的输入流以 " 结尾,该引号将被截断。但是,如果您的输入以换行符而不是 " 终止,这将执行您想要的操作。

OTOH,你可能只想做:

perl -wpE 'BEGIN{$/=}; y/,/;/ if $in; $in = ! $in if $_ eq "\""'

它读取一个字符并使用一个简单的状态机。 ($_ 是当前字符,因此 $in = ! $in 会在看到双引号时更改状态,并且音译仅在 $in 为 non-zero 时发生。)

如果你/真的/想要使用 sed,你可以做整行替换并在现有表达式的开头包含一个像 ^(([^"]*"[^"*]")*[^"]*) 这样的子句,以确保匹配引号是 "odd".