RegExp-匹配尽可能短的数量似乎不起作用

RegExp-匹配尽可能短的数量似乎不起作用,regex,linux,Regex,Linux,我想删除CSV文件中匹配双引号中的逗号。这里的关键是它必须在匹配的双引号之间。此RexExp似乎不起作用: ".*?,.*?" 如果引入问号,它不会发现任何东西。因此,以下方法不起作用: s/\(".*?\),\(.*?"\)/\1;\2/g 下一行是输入测试行。它与最短的不匹配 21,C,101,1,,W,D,,"AAAAAAAA,, RBBBBBB,",CCCCCCCCCC DD EEEEEEEEEE,FFFFFF GGGGGGG HHHHHHHHH,III 101 JJ,,,,KKKK

我想删除CSV文件中匹配双引号中的逗号。这里的关键是它必须在匹配的双引号之间。此RexExp似乎不起作用:

".*?,.*?"
如果引入问号,它不会发现任何东西。因此,以下方法不起作用:

s/\(".*?\),\(.*?"\)/\1;\2/g
下一行是输入测试行。它与最短的不匹配

21,C,101,1,,W,D,,"AAAAAAAA,, RBBBBBB,",CCCCCCCCCC DD EEEEEEEEEE,FFFFFF GGGGGGG HHHHHHHHH,III 101 JJ,,,,KKKKKKK LLLLLLLL M'MMMM N,"OOO, P'PPPP QQQQQQQQ RR R",SSSSSSSSSSSS TTTTTTTTTT,UUU 101 VV,,,,,12/1/1998,1/1/2050,ZZZZZZ

我想将“aaaaaaa,RBBBBBB,”中的逗号改为分号“aaaaaaa;;RBBBBBB;”,并“OOO,p'PPPP qqqqqqqqqq RR”“oo;p'PPPP qqqqqqqqqqqq RR R R”,而不更改输入行中的任何其他逗号。

gnu awk with
FPAT
可以处理此问题:

awk -v FPAT='"[^"]*"|[^,]*' -v OFS=, '{for(i=1; i<=NF; i++) gsub(/,/, ";", $i)} 1' file.csv

您的正则表达式有一个基本问题:
可以匹配任何字符,包括引号。懒惰量词并不能解决这个问题,它只是使它在简单的情况下工作

另外,如果有多个逗号,您想怎么做

请尝试以下方法:

"[^",]*?,[^",]*"
或者,要在引号内处理多个逗号:

"([^",]*?,)+[^",]*"

请注意,这个正则表达式仍然可以匹配不需要的文本,如果您想避免这种情况,那么您必须使匹配行起始锚点和实数对引号变得更加复杂,而不仅仅是其中包含逗号的任何两个引号。

我已经测试了这一点,以处理您的示例输入:

s/\("[^"]*\),\([^"]*"\)/\1;\2/g
在OSX和linux上执行,结果相同:

$ echo 21,C,101,1,,W,D,,\"AAAAAAAA,, RBBBBBB,\",CCCCCCCCCC DD EEEEEEEEEE,FFFFFF GGGGGGG HHHHHHHHH,III 101 JJ,,,,KKKKKKK LLLLLLLL M\'MMMM N,\"OOO, P\'PPPP QQQQQQQQ RR R\",SSSSSSSSSSSS TTTTTTTTTT,UUU 101 VV,,,,,12/1/1998,1/1/2050,ZZZZZZ | sed -e 's/\("[^"]*\),\([^"]*"\)/\1;\2/g'
21,C,101,1,,W,D,,"AAAAAAAA,, RBBBBBB;",CCCCCCCCCC DD EEEEEEEEEE,FFFFFF GGGGGGG HHHHHHHHH,III 101 JJ,,,,KKKKKKK LLLLLLLL M'MMMM N,"OOO; P'PPPP QQQQQQQQ RR R",SSSSSSSSSSSS TTTTTTTTTT,UUU 101 VV,,,,,12/1/1998,1/1/2050,ZZZZZZ

您的正则表达式对于CSV(如
“ab”、“cd”
)将失败。Regex并不是CSV真正的工具,但如果您在更高的层次上描述您的问题,我们可以提供帮助。
在量词后面表示“尽可能少”(惰性匹配)。如果问号表示“尽可能少”为什么它至少找不到一个没有问号的?您的提案会在不匹配的引号内更改逗号。例如,在
“aaaa bbbb”,xxxx,“bbb”
@Guasqueño中,我已经更新了我的答案,以包括命令结果。您的示例输入在不受正则表达式影响的匹配双引号之间有逗号。无论如何,我不会在匹配的双引号中处理多个逗号。谢谢Lucero。只要方框中没有逗号,并且没有使用问号,您的解决方案就可以工作。有些人认为添加问号的模式找不到。"[^"]*,[^"]*". 我不明白为什么问号不起作用。我将继续测试。更正我写的内容,如果引号中只有一个逗号需要使用
s/../g
替换,则您的解决方案部分有效(将逗号保留在两个方括号中)。你说得对。此外,中带有问号的RegExp不知何故也找不到任何内容。此外,如果要替换的逗号不止一个,则我无法将第二个RegExp与
s/../g
中的
\1
\2
一起使用。@Guasqueño,有不同的regex风格和容量,因此您的mielage可能会因实际使用的工具而异。尽管如此,我还是用JavaScript正则表达式和.NET正则表达式引擎成功地测试了它。如果问号不起作用,您可以删除它,在我的例子中它不会破坏正则表达式,但它可能表明您使用的正则表达式引擎不支持惰性量词。关于caputed组,您可以使用
“(?:[^,]*,)+[^,]*”
来避免捕获。我使用的是Redhat Linux 2.6.32和TextPad 4.5.0。他们中没有人喜欢懒惰的问号。我将进一步调查用于避免捕获的问号。这对我来说是新鲜事。谢谢。更具体地说,我试图在Linux中使用
vi
内部的正则表达式。对不起。我运行了你的命令,得到了不应该出现的分号。我得到了这个:
21;C101;1.WD“aaaaaaa;;,RBBBBBB;”;CCCC、DD、EEEE;FFFFFF,GGGGGGG,HHHHHHHHHHHH;三、 101,JJ;;;;kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk;“OOO;,P'PPPP,qqqqqq,RR,R”;SSSSSSSS,TTTTTTTT;UUU,101,VV;;;;;12/1/1998;1/1/2050;ZZZZZZ
您运行的确切命令是什么,您的awk版本是什么?我的回答中也包含了awk的输出。
$ echo 21,C,101,1,,W,D,,\"AAAAAAAA,, RBBBBBB,\",CCCCCCCCCC DD EEEEEEEEEE,FFFFFF GGGGGGG HHHHHHHHH,III 101 JJ,,,,KKKKKKK LLLLLLLL M\'MMMM N,\"OOO, P\'PPPP QQQQQQQQ RR R\",SSSSSSSSSSSS TTTTTTTTTT,UUU 101 VV,,,,,12/1/1998,1/1/2050,ZZZZZZ | sed -e 's/\("[^"]*\),\([^"]*"\)/\1;\2/g'
21,C,101,1,,W,D,,"AAAAAAAA,, RBBBBBB;",CCCCCCCCCC DD EEEEEEEEEE,FFFFFF GGGGGGG HHHHHHHHH,III 101 JJ,,,,KKKKKKK LLLLLLLL M'MMMM N,"OOO; P'PPPP QQQQQQQQ RR R",SSSSSSSSSSSS TTTTTTTTTT,UUU 101 VV,,,,,12/1/1998,1/1/2050,ZZZZZZ