【问题标题】:Regex pattern for parsing用于解析的正则表达式模式
【发布时间】:2013-12-31 05:26:27
【问题描述】:

我需要一个匹配以下各项的模式:

  • 除 (:=#\) 之外的非空白符号字符串,后跟 :,再后跟除 (:=#\) 之外的非空白符号字符串或
  • 空格或制表符后跟 1 个或多个非空白字符或
  • a # 后跟任何内容或
  • 一行包含一个或多个空格或制表符或
  • 以前没有发现的东西的包罗万象。

我目前的模式如下: ^([\\S&&[^\\n:=#\\\\]]+):([[\\s&&[^\\n]][\\S&&[^\\n=:#\\\\]]*]*)|^[ \\t](\\S[\\s\\S&&[^\\n]]*)|(^#[\\s\\S&&[^\n]]+)|^([\\s&&[^\\n\\x0B\\f\\r]]+)|([[\\s\\S]&&[^\\n]]+)

我正在使用 findwithinhorizo​​n(this Pattern, 0)

将它与 Scanner 一起使用

在下面的块中,inp 是缓冲的扫描器,_pat 是上面的模式。 我遇到了将字符串分配给错误匹配组的问题。

前:

bob: cat dog
 meow

在此扫描仪中运行此程序后,我在匹配组 2(“猫狗”)上调用 .split(\\s+) 后得到一个空字符串,并且“喵”与组 6(我的错误组)而不是组 3 匹配.

    BufferedReader buf =
            new BufferedReader(new FileReader(makeFile));
    Scanner inp = new Scanner(buf);


    while (inp.findWithinHorizon(_pat, 0) != null) {
        int i = 1;
        MatchResult mat = inp.match();
        for (; i <= TOTAL_VALS; i++) {
            if (mat.group(i) != null) {
                break;
            }
        } 

【问题讨论】:

    标签: java regex string java.util.scanner


    【解决方案1】:

    这个正则表达式会将一行解析成适当的组:

    ([^\s:=#\\]+\s*:\s*(?:[^\s:=#\\]+\s*))|([ \t]\S+)|(#.*)|(\s*)|(.*)
    

    请注意,您的第一个条件实际上并不匹配 bob: cat dog。条件应该是这样的:

    • :=#\ 之外的非空白符号字符串(可选地后跟空格,后跟: 可选地后跟空格,后跟除 (:=#) 之外的一个非空白符号字符串,用空格或分隔符)

    示例用法:

    String regex = "([^\\s:=#\\\\]+\\s*:\\s*(?:[^\\s:=#\\\\]+\\s*)+)|([ \t]\\S+)|(#.*)|(\\s*)|(.*)";
    Pattern p = Pattern.compile(regex);
    for (String line : lines) {
        Matcher m = p.matcher(line);
        m.matches();
        for(int i=1;i<m.groupCount();i++) {
            System.out.println(i+": "+m.group(i));
        }
        System.out.println();
    }
    

    对于您的输入数据:

    bob: cat dog
     meow
    

    输出将是

    1: bob: cat dog
    2: null
    3: null
    4: null
    
    1: null
    2:  meow
    3: null
    4: null
    

    【讨论】:

      【解决方案2】:

      查看正则表达式的一小部分(删除额外的转义)

      [\S&&[^\n:=#\\]]+
      

      这在正则表达式语法中没有任何意义。我从您的描述中猜测,模式的这一部分应该是指“不是空格的字符序列,也不是换行符或:=#\。”这就是您为此编写正则表达式模式的方式:

      [^\s:=#\\]+
      

      即"一个或多个非空格字符,:=#\

      因此,一次满足您的要求:

      • 除 (:=#\) 之外的非空白符号字符串,后跟 :,再后跟除 (:=#\) 之外的非空白符号字符串或

        [^\s:=#\\]+:[^\s:=#\\]
        
      • 一个空格或制表符后跟 1 个或多个非空白字符或

        [ \t]\S+
        
      • a # 后跟任何内容或

        #.*
        
      • 由一个或多个空格或制表符组成的一行。

        [ \t]+
        

      把它们放在一起:

      ^([^\s:=#\\]+:[^\s:=#\\]|[ \t]\S+|#.*|[ \t]+)$
      

      并恢复多余的转义字符,使其可以放在双引号字符串中:

      ^([^\\s:=#\\\\]+:[^\\s:=#\\\\]|[ \\t]\\S+|#.*|[ \\t]+)$
      

      我省略了“catchall”要求,因为我不清楚它为什么有用:像something|something else|a third thing|.* 这样的正则表达式保证匹配任何字符串,为了简单起见,还不如替换为.* .

      【讨论】:

      • 谢谢!我想我可能在第一个要求中搞砸了规范,尽管我的意思是说 : 后跟零个或多个空格分隔的非空格字符串。我猜会是这个样子? [^\s:=#\]+:[^\s:=#\]*
      • 我还想知道是否在整个过程中放置​​括号来设置捕获组如下会产生任何不良影响? ^(([^\\s:=#\\\]+):([^\\s:=#\\\\]*)|([\\t]\\S+)|(#.*) |([ \\t]+)|(.*))$
      • 一系列由空格隔开的非空格字符串只是表示一堆任意字符。 :-) 所以你可以完全从字符串的后半部分删除\s 并得到[^\s:=#\]+:[^:=#\]*
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      • 2012-07-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-17
      • 1970-01-01
      相关资源
      最近更新 更多