正则表达式组匹配返回错误的值

时间:2015-02-03 18:03:37

标签: java regex

Regex=
 "^\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)(\\s+(\\S+(\\s+(\\S+))?))?(\\s+(\\S+))?\\s*";

input= "    1  ABC    DEF  GHI   JKL   PQR   ";

在上面的输入文本中,正则表达式匹配,但是有些情况下JKL可以是空格的单词,如" JKL MNO"所以正则表达式我已经像可选的

一样
(\\s+(\\S+))?

虽然得到该组我的错误值,即

G1: 1 G2: ABC G3: DEF G4: GHI **G6: JKL PQR** G8:PQR

G6当MNO出现时,应该只有JKL或JKL MNO作为一个单词,你能否弄清楚我做错了什么。

5 个答案:

答案 0 :(得分:2)

您观察到的行为是正则表达式的预期行为。捕获组从组的开始paren开始,以其结束paren结束。如果捕获组A包含捕获组B,则A将包含所有B。

那是

(\\s+(\\S+(\\s+(\\S+))?))?

匹配
   JKL PQR

第1组将是

   JKL PQR
第2组将是
JKL PQR
第3组将是
 PQR
第4组将是
PQR

如果您希望JKL成为一个组,您可以使用捕获组和非捕获组的组合,例如:

(?:\\s+(?:(\\S+)(?:\\s+(\\S+))?))?

然后,第1组将为JKL,第2组将为PQR

答案 1 :(得分:1)

发生的事情是,(\\s+(\\S+))?部分的内部(\\s+(\\S+(\\s+(\\S+))?))读取PQR并且正则表达式的最后部分 - (\\s+(\\S+))?是可选的,最终无法读取任何内容

使最后一部分不可选将解决问题。但是,如果您不打算捕获它们,则可以避免使用这么多捕获组,例如,可以使空格不被捕获 - (?:\\s+)

所以,您可以将正则表达式更改为:

String str = "^\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)(?:\\s+(\\S+(?:\\s+\\S+)?))?(?:\\s+(\\S+))\\s*";

请注意这里关注的部分:

(?:\\s+(\\S+(?:\\s+\\S+)?))?

正如您所看到的,只有一个捕获组,足以捕获JKLJKL MNO(如果存在)。如果您还想单独捕获MNO,请将内部\\S+也设为捕获组。

答案 2 :(得分:0)

如果PQR是强制性的,则删除?中的最后一个(\\s+(\\S+))?即可。

这是因为RegEx是贪婪的,所以如果最后一部分是可选的(这是问题),它将在第8组中PQR

完整的正则表达式应该是: "^\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)(\\s+(\\S+(\\s+(\\S+))?))?(\\s+(\\S+))\\s*"

答案 3 :(得分:0)

我认为你在寻找的是:

^\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)(\\s+(\\S+(\\s+(\\S+))??))?(\\s+(\\S+))?\\s*$

该模式使用不情愿(非贪婪)量词??。这意味着仅在必要时才匹配组7。

如果缺少" MNO",则组7根本不匹配。第6组仅包含" JKL"

如果您使用字符串锚点的结尾,则会强制" MNO"与第7组匹配,即使此组是可选的,但是不情愿的量词?? 。第6组包含" JKL MNO"

没有不情愿的量词,因为模式是从左到右评估的," PQR"将与第7组匹配(因为量词?默认是贪婪的)并且第9组将不匹配因为它是可选的。

注意:没有无用的捕获组,您可以写:

^\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)(?:\\s+(?:(\\S+)(?:\\s+(\\S+))??))?(?:\\s+(\\S+))?\\s*$

答案 4 :(得分:0)

而不是使用让我的眼睛游泳的正则表达式,我会去分手:

String[] toks = input.split( "\\s+" );

toks.length必须至少为4,以便我们toks[0]toks[3]。现在:

  • toks.length == 5:这应该是" JKL"
  • toks.length == 7:我们有" v" in toks [4]和toks [5]以及PQR in toks [6]

那么toks.length == 6怎么样?是可选的" MNO"强于可选的" PQR"还是反过来呢?在任何一种情况下,您都可以使用String []及其长度更轻松地决定。

(我知道" JKL"和" MNO"之间的空格数会以这种方式丢失。如果真的很重要,可以从原来的字符串中检索到努力。)