正则表达式以提取组中的子字符串

时间:2014-09-19 15:18:22

标签: java regex

我想使用正则表达式从以下输入中提取名称。

Student Names:
    Name1
    Name2
    Name3

Parent Names:
    Name1
    Name2
    Name3

我使用以下方法来匹配数据,我不应该修改方法。我必须提出适用于此方法的正则表达式。

public void parseName(String patternRegX){

        Pattern patternDomainStatus = Pattern.compile(patternRegX);
        Matcher matcherName = patternName.matcher(inputString);
        List<String> tmp=new ArrayList<String>();

        while (matcherName.find()){
            if (!matcherName.group(2).isEmpty())
                tmp.add(matcherName.group(2));
        }
}

我想出了一个正则表达式,可以得到我想要的结果,但我发现的问题是分组在方括号([])中不起作用。

  

private String studentRegX =“(学生姓名:\ n [+ (\ S +) \ n] + \ n)”;

我现在正在使用以下正则表达式,但这只是我每个集合中的姓氏。

private String studentRegX="Student Names:\\n( +(\\S+)\\n)+\\n";
private String parentRegX="Parent Names:\\n( +(\\S+)\\n)+\\n";

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:0)

首先,我希望您可以稍微更改parseName方法,因为它不会编译。 patternDomainStatuspatternName可能应该引用同一个对象:

    Pattern pattern = Pattern.compile(patternRegX);
    Matcher matcherName = pattern.matcher(inputString);

其次,你需要以不同的方式考虑你的正则表达式。

现在,你的正则表达式试图匹配整个块中的多个名称。但是matcherName.find()找到&#34;输入序列的下一个子序列与模式匹配&#34; (根据javadoc)。

所以你想要的是匹配单个名称的正则​​表达式。 matcherName.find()将循环遍历与该正则表达式匹配的字符串的每个部分。

答案 1 :(得分:0)

如果您还不熟悉重复捕获组和捕获重复组之间的区别,那么值得一读。其中一个资源是http://www.regular-expressions.info/captureall.html,但其他资源也可以。

如果你已经知道了这个差异,并试图捕捉一个重复的群体已经与你上面写的内容,那么请编辑你的帖子来解释你想要做什么(逐个字母的解释会是理想的,所以我们看到你理解的和你不理解的东西,所以我们可以帮助你解决任何问题。

我看到我认为的解决方案,但由于这显然是家庭作业,我不愿意简单地给你。但我很乐意帮助你搞清楚。

---编辑:---

您只获得一场比赛,因为正则表达式要求“学生姓名:”或“家长姓名:”在每次匹配中,因此您只能匹配一次。为了让你的正则表达式连续多次匹配(根据while (matcherName.find())的要求),你需要从正则表达式中获取“学生姓名:”和“父姓名:”,这样正则表达式可以重复匹配。

很容易获得所有名称(学生和家长),只需要一个正则表达式,查找换行符后跟一个或多个空格然后是文本。挑战在于区分学生姓名(位于“父姓名:”行之前)和父姓名(位于“父姓名:”行之后)。区分它们的关键概念是lookaheads,它可以是正面的,也可以是负面的。看看它们,看看你是否可以找出如何使用前瞻实现这一点。

此外,您可能会发现组#2不是您真正想要使用的组。不幸的是,组号是硬编码的,但是既然如此,你可以调整你的正则表达式,使用(?:stuff)语法使组不能被捕获。这样可以减少组的数量,并确保您真正想要的组是#2。

答案 2 :(得分:0)

因为正则表达式与算法能力关系不大,所以答案是:

  • 在Windows上,遗憾的是换行符#34; \ r \ n&#34;。
  • 我检查是否有换行符,并且名称前至少有一些空格。
  • 该名称可能有空格。
  • 通过后视我检查&#34;父姓名&#34;如下。

然后

Pattern.compile("(?s)(?<=\n)[ \t]+([^\r\n]*)\r?\n(?=.*Parent Names)");
//               ~~~~ '.' also matches newline
//                   ~~~~~~~ look-behind must be newline
//                          ~~~~~~ whitespace (spaces/tabs)
//                                ~~~~~~~~~~ group 1, name
//                                               ~~~~~~~~~~~~~~~~~~~~ look-ahead

不用说,有点不同的算法会更加稳固和可理解。

要使其成为组(2)而不是上述组(1),您可以在之前引入额外的大括号:([ \t]+)

答案 3 :(得分:0)

可以在单个正则表达式中使用\G锚点来完成 这为一个小的正则表达式算法实力打开了它。 每场比赛将是:

  • 组1不为空/空 - 新学生组,组3将包含第一个学生姓名。
  • 组2不为NULL /空 - 新的父组,组3将包含第一个父名。
  • 第3组永远不会为空/空 - 第一个/下一个学生或父母名称取决于哪个 第1组或第2组最后匹配。

在所有情况下,第3组将包含一个已经修剪并准备放入数组的名称。


 # "~(?mi-)(?:(?!\\A)\\G|^(?:(Student)|(Parent))[ ]Names:)\\s*^(?!(?:Student|Parent)[ ]Names:)[^\\S\\r\\n]*(.+?)[^\\S\\r\\n]*$~"

 (?xmi-)                     # Inline 'Expanded, multiline, case insensitive' modifiers
 (?:
      (?! \A )                    # Here, matched before, give Name a first chance
      \G                          # to match again.
   |  
      ^                           # BOL
      (?:
           ( Student )                 # (1), New 'Student' group
        |  ( Parent )                  # (2), New 'Parent' group
      )
      [ ] Names: 
 )
                             # Name section
 \s*                         # Consume all whitespace up until the start of a Name line
 ^                           # BOL 
 (?!
      (?: Student | Parent )      # Names only, Not the start of Student/Parent group here
      [ ] Names:
 )
 [^\S\r\n]*                  # Trim leading whitespace ( can use \h if supported )
 ( .+? )                     # (3), the Name
 [^\S\r\n]*                  # Trim trailing whitespace ( can use \h if supported )
 $                           # EOL