2010-10-29 105 views
1

我知道,我知道,现在我有两个问题,但这里的正则表达式意味着我不必编写两个复杂的循环。相反,我有一个只有我明白的正则表达式,我才会受雇于yonks。Java replaceAll()&split()违规

我有一个字符串,说stack.overflow.questions[0].answer[1].postDate,我需要得到[0]和[1],最好在数组中。 “简单!”我的神经元惊叹,只需在输入字符串中使用正则表达式和split方法;所以我想出了这个:

String[] tokens = input.split("[^\\[\\d\\]]"); 

这将产生以下:

[, , , , , , , , , , , , , , , , [0], , , , , , , [1]] 

哦,亲爱的。所以,我想, “你会做replaceAll在这种情况下?”:

String onlyArrayIndexes = input.replaceAll("[^\\[\\d\\]]", ""); 

它生产:

[0][1] 

嗯。为什么这样?我正在寻找一个包含“[0]”作为第一个元素和“[1]”作为第二个元素的双元素字符串数组。为什么Split在这里不起作用,当Javadoc声明他们都使用Pattern类时,按照Javadoc

总之,我有两个问题:为什么用split()通话产生大阵与看似随意的空格字符我是正确的思维中的replaceAll工作,因为正则表达式替换所有字符不匹配“[”一个数字和“]”?我错过了什么,这意味着我期望他们产生类似的输出(好吧,这是三个,请不要回答这个问题的线索?)。

回答

4
从我所看到的

很好的split没有工作,它给你一个数组,用于存放每个匹配的字符串split,而不是一组中间带数字的括号。

至于replaceAll我认为你的假设是正确的。它将删除所有内容(用""替换该匹配项),这不是您想要的。

API documentation

拆分此字符串周围的 给定的正则表达式匹配。

此方法的工作原理就好像调用 双参数拆分方法,其中 的给定表达式和极限参数 为零。尾随的空字符串是 因此不包含在 结果数组中。

字符串 “BOO:和:foo” 的,例如, 产生具有 以下结果这些表达式:由您提供的正则表达式定义的边界

Regex  Result 
:  { "boo", "and", "foo" } 
o  { "b", "", ":and:f" } 
+0

谢谢,这是事实上,split为我的正则表达式的每个匹配给了我一个元素;这是我不明白的! – 2010-10-29 08:29:39

2

这不是直接回答你的问题,但我想告诉你一个很好的API,将适合你的需要。

从谷歌Guava退房Splitter

因此,对于你的榜样,你会使用这样的:

Iterable<String> tokens = Splitter.onPattern("[^\\[\\d\\]]").omitEmptyStrings().trimResults().split(input); 

//Now you get back an Iterable which you can iterate over. Much better than an Array. 
for(String s : tokens) { 
    System.out.println(s); 
} 

此打印:
0
1

+0

一个很好的建议,谢谢。现在我只在这个特定的例子中使用正则表达式,但是如果我需要进一步的话,我会去番石榴。 – 2010-10-29 08:29:02

+0

Google Guava支持正则表达式。正如我在示例中所展示的那样。 – 2010-10-29 08:30:48

2

split分割,所以这并不令人惊讶,你得到很多条目  —几乎字符串中的所有字符都与你的正则表达式匹配,因此,根据定义,它们是出现分割的边界。

replaceAll替换与您替换的正则表达式匹配,您的情况为空白字符串。

如果你试图抓住01,这是一个简单的循环:

String text = "stack.overflow.questions[0].answer[1].postDate"; 
Pattern pat = Pattern.compile("\\[(\\d+)\\]"); 
Matcher m = pat.matcher(text); 
List<String> results = new ArrayList<String>(); 
while (m.find()) { 
    results.add(m.group(1)); // Or just .group() if you want the [] as well 
} 
String[] tokens = results.toArray(new String[0]); 

或者,如果它是总是正是其中的两个:

String text = "stack.overflow.questions[0].answer[1].postDate"; 
Pattern pat = Pattern.compile(".*\\[(\\d+)\\].*\\[(\\d+)\\].*"); 
Matcher m = pat.matcher(text); 
m.find(); 
String[] tokens = new String[2]; 
tokens[0] = m.group(1); 
tokens[1] = m.group(2); 
1

的问题是那split这里是错误的操作。

在Ruby中,我会告诉你string.scan(/\[\d+\]/),这将使你的阵列["[0]","[1]"]

Java没有一个单一的方法相当,但我们可以用下面写一个scan方法:

public List<String> scan(String string, String regex){ 
    List<String> list = new ArrayList<String>(); 
    Pattern pattern = Pattern.compile(regex); 
    Matcher matcher = pattern.matcher(string); 
    while(matcher.find()) { 
     list.add(matcher.group()); 
    } 
    return retval; 
} 

,我们可以把它作为scan(string,"\\[\\d+\\]")

等效Scala代码是:

"""\[\d+\]""".r findAllIn string 
+0

一个有趣的方法;谢谢! – 2011-07-04 08:00:53