替换引号内的所有逗号(或反义)

Replacing all commas inside quotations marks (or the inverse)

假设我有以下句子

Apples, "This, is, a test",409, James,46,90

我想把引号里面的逗号改成;。或者,也可以是引号外的相同字符 ;。到目前为止,我想到了类似

perl -pe 's/(".*)\K,(?=.*")/;/g' <mystring>

但是,这只匹配引号内的最后一个逗号,因为我正在用 \K 重新启动正则表达式引擎。我还尝试了一些正则表达式来更改引号外的逗号,但我无法让它工作。

请注意,引号外的逗号后的空格是故意留在那里的,因此

perl -pe 's/,\s/;/g' <mystring>

不是有效答案。

所需的输出将是

Apples, "This; is; a test",409, James,46,90

或者

Apples; "This, is, a test";409; James;46;90

关于如何解决这个问题有什么想法吗?

我会使用实际的 CSV 解析器,而不是尝试使用正则表达式破解某些东西。非常有用的 Text::AutoCSV 模块可以轻松地将 one-liner:

中的逗号字段分隔符转换为分号
$ echo 'Apples, "This, is, a test",409, James,46,90' |
    perl -MText::AutoCSV -e 'Text::AutoCSV->new(out_sep_char => ";")->write()'
Apples;"This, is, a test";409;James;46;90

对于 non-perl 解决方案,来自 csvkitcsvformat 是另一个方便的工具,尽管更难获得相同的引用:

$ echo 'Apples, "This, is, a test",409, James,46,90' |
    csvformat -S -U2 -D';'
"Apples";"This, is, a test";"409";"James";"46";"90"

或者(自我提升警报!)我的 tawk 实用程序(也不会得到相同的引号):

$ echo 'Apples, "This, is, a test",409, James,46,90' |
    tawk -csv -quoteall 'line { set F(1) $F(1); print }' OFS=";"
"Apples";" This, is, a test";"409";" James";"46";"90"