【问题标题】:Regex not matching words delimited by whitespace正则表达式不匹配由空格分隔的单词
【发布时间】:2011-11-09 08:59:18
【问题描述】:

我有一个输入字符串,它将遵循模式/user/<id>?name=<name>,其中<id> 是字母数字但必须以字母开头,<name> 是一个可以有多个空格的纯字母字符串。一些匹配示例如下:

/user/ad?name=a a
/user/one111?name=one ONE oNe
/user/hello?name=world

我想出了以下正则表达式:

String regex = "/user/[a-zA-Z]+\\w*\\?name=[a-zA-Z\\s]+";

以上所有示例都与正则表达式匹配,但它只查看<name> 中的第一个单词。序列\s 不应该允许我有空格吗?

我为测试它正在做什么而编写的代码是:

String regex = "/user/[a-zA-Z]+\\w*\\?name=[a-zA-Z\\s]+";
// Check to see that input matches pattern
if(Pattern.matches(regex, str) == true){
   str = str.replaceFirst("/user/", "");
   str = str.replaceFirst("name=", "");
   String[] tokens = str.split("\\?");
   System.out.println("size = " + tokens.length);
   System.out.println("tokens[0] = " + tokens[0]);
   System.out.println("tokens[1] = " + tokens[1]);
} else
    System.out.println("Didn't match.");

例如,一项测试可能如下所示:

/user/myID123?name=firstName LastName
size = 2
tokens[0] = myID123
tokens[1] = firstName

而期望的输出是

tokens[1] = firstName LastName

我怎样才能改变我的正则表达式来做到这一点?

【问题讨论】:

    标签: java regex


    【解决方案1】:

    不确定您认为代码中的问题是什么。 tokens[1] 将在您的示例中确实包含 firstName LastName。

    这是一个 ideone.com demo 显示这个。


    但是,您是否考虑过为 id 和 name 使用捕获组。

    如果你这样写

    String regex = "/user/(\\w+)\\?name=([a-zA-Z\\s]+)";
    
    Matcher m = Pattern.compile(regex).matcher(input);
    

    你可以通过m.group(1)和m.group(2)获取myID123和firstName LastName

    【讨论】:

    • 次要 nitpick:此正则表达式还匹配以数字开头的 id。
    • True.. OP 没有 ;) 因为它被标记为作业,我将把它留作练习 ;)
    • 谢谢!我不知道分组,它确实有助于清理我的代码。
    【解决方案2】:

    我在您的代码中没有发现任何错误,但您可以像这样捕获组:

        String str = "/user/myID123?name=firstName LastName ";      
        String regex = "/user/([a-zA-Z]+\\w*)\\?name=([a-zA-Z\\s]+)";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str);
        if(m.find()) {
            System.out.println(m.group(1) + ", " + m.group(2));
        }
    

    【讨论】:

      【解决方案3】:

      问题是* 默认是贪婪的(它匹配整个字符串),所以你需要通过添加? 来修改你的正则表达式(让它不情愿):

          List<String> str = Arrays.asList("/user/ad?name=a a", "/user/one111?name=one ONE oNe", "/user/hello?name=world");
          String regex = "/user/([a-zA-Z]+\\w*?)\\?name=([a-zA-Z\\s]+)";
      
          for (String s : str) {
              Matcher matcher = Pattern.compile(regex).matcher(s);
              if (matcher.matches()) {
                  System.out.println("user: " + matcher.group(1));
                  System.out.println("name: " + matcher.group(2));
              }
          }
      

      输出:

      user: ad
      name: a a
      user: one111
      name: one ONE oNe
      user: hello
      name: world
      

      【讨论】:

      • 也许我做错了什么,但这并没有改变我的任何东西:(不过感谢您的回复!
      • 你需要重构你的代码,并像我的例子一样使用 Matcher 和 Pattern 类。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-15
      • 2018-06-12
      • 2013-07-09
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      • 2023-01-20
      相关资源
      最近更新 更多