2009-11-01 64 views
1

我有这个字符串:正则表达式,代替双引号之间的所有逗号

1001,"Fitzsimmons, Des Marteau, Beale and Nunn",109,"George","COD","Standard",,109,8/14/1998 8:50:02 

我会用什么正则表达式用管替换 "Fitzsimmons, Des Marteau, Beale and Nunn"逗号|所以它是:

"Fitzsimmons| Des Marteau| Beale and Nunn" 

应该澄清一点,我正在使用逗号分隔这个字符串,所以我想"Fitzsimmons, Des Marteau, Beale and Nunn"是一个字符串。我打算在分割后用逗号替换|

+1

这似乎是这将是WAY更快只是给自己写一个小的状态机循环,并用它做。 – 2009-11-01 22:15:11

+0

使用已经写入的CSV解析器就会更快,就像链接到的一个jheddings一样。 – 2009-11-01 22:25:43

+0

如果您要尽量使用正则表达式来进行替换,以便您可以使用常规拆分,那么为什么不使用正则表达式来进行拆分呢?这样你就不会不小心翻译原始源代码中的'|'(如果有的话) – SingleNegationElimination 2009-11-01 22:27:53

回答

4

我曾尝试使用StringTokenizer,但它并不能很好的工作,所以在这里,这似乎做你想要什么代码:

import java.util.*; 

public class JTest 
{ 
    public static void main(String[] args) 
    { 
    String str = "1001,\"Fitzsimmons, Des Marteau, Beale and Nunn\",109,\"George\",\"COD\",\"Standard\",,109,8/14/1998 8:50:02"; 
    String copy = new String(); 

    boolean inQuotes = false; 

    for(int i=0; i<str.length(); ++i) 
     { 
     if (str.charAt(i)=='"') 
      inQuotes = !inQuotes; 
     if (str.charAt(i)==',' && inQuotes) 
      copy += '|'; 
     else 
      copy += str.charAt(i); 
     } 

    System.out.println(str); 
    System.out.println(copy); 
    } 
} 
4

尽管可以使用正则表达式,但首先将行分割成字段然后再进行替换会更清晰。有一个很好的(免费的)用于解析称为opencsv的CSV文件的java库。

1

我相信这对正则表达式来说会很困难。麻烦的是,正则表达式将不得不计算引号来确定它是否在两个引号内。

实际上,.NET正则表达式引擎可以使用它的balanced matching功能。但我不认为Java具有这种功能,我想不出没有它的可靠方法。

您可能需要编写一些过程代码来完成此操作。

1

好了,这是一个CSV文件,所以我使用Ruby的内置CSV库。然后,例如,您不必知道如何处理转义的引号。

require 'csv' 
string =<<CSV 
1001,"Fitzsimmons, Des Marteau, Beale and Nunn",109,"George","COD","Standard",,109,8/14/1998 8:50:02 
CSV 
csv=CSV.parse string 
csv.each{|row| row.each {|cell| cell.gsub!(",","|") if cell.is_a?(String)}} 
outstring = "" 
CSV::Writer.generate(outstring){|out| csv.each {|row| out<<row}} 
+0

OP用Java标记了这个问题,所以我假设这是选择的语言。 – jheddings 2009-11-01 22:30:31

+0

这不是一个红宝石问题。 – SingleNegationElimination 2009-11-01 22:30:50

+0

所以也许在Java中尝试http://sourceforge.net/projects/javacsv/。 – 2009-11-02 01:56:21

2

这里有一点的Python,似乎这样的伎俩:

>>> import re 
>>> p = re.compile('["][^"]*["]|[^,]*') 
>>> x = """1001,"Fitzsimmons, Des Marteau, Beale and Nunn",109,"George","COD","Standard",,109,8/14/1998 8:50:02""" 
>>> y = p.findall(x) 
>>> ','.join(z.replace(',','|') for z in y if z) 
'1001,"Fitzsimmons| Des Marteau| Beale and Nunn",109,"George","COD","Standard",109,8/14/1998 8:50:02' 

好像这个代码转成代码高尔夫问题:-)

哎呀...错过了Java标签。

3

嘿布兰登,你可以很容易地使用RE来做到这一点,通过使用后面和展望。见下文

String cvsString = "1001,\"Fitzsimmons, Des Marteau, Beale and Nunn\",109,\"George\",\"COD\",\"Standard\",,109,8/14/1998 8:50:02"; 
String rePattern = "(?<=\")([^\"]+?),([^\"]+?)(?=\")"; 
// first replace 
String oldString = cvsString; 
String resultString = cvsString.replaceAll(rePattern, "$1|$2"); 
// additional repalces until until no more changes 
while (!resultString.equalsIgnoreCase(oldString)){ 
    oldString = resultString; 
    resultString = resultString.replaceAll(rePattern, "$1|$2"); 
} 

结果字符串代码会 1001,"Fitzsimmons| Des Marteau| Beale and Nunn",109,"George","COD","Standard",,109,8/14/1998 8:50:02

NingZhang.info

+0

这是一个有趣的方法。虽然我不明白你为什么需要向前看和向后看。这个正则表达式不会工作吗? '(“[^”,] ++),([^“] ++”)' – 2009-11-02 13:46:55

+0

那么前面/后面的查看是必需的,这样任何令牌都可以包含逗号',',只要它是双引号。否则,令牌不会被正确解析。 – Ning120 2010-02-04 01:31:39

相关问题