【问题标题】:Using Java to find substring of a bigger string using Regular Expression使用Java使用正则表达式查找更大字符串的子字符串
【发布时间】:2010-10-10 16:29:06
【问题描述】:

如果我有这样的字符串:

FOO[BAR]

我需要一种通用的方法来从字符串中取出“BAR”字符串,这样无论方括号之间的字符串是什么,它都可以得到该字符串。

例如

FOO[DOG] = DOG
FOO[CAT] = CAT

【问题讨论】:

    标签: java regex string


    【解决方案1】:

    您应该能够使用非贪婪量词,特别是 *?。您可能需要以下内容:

    Pattern MY_PATTERN = Pattern.compile("\\[(.*?)\\]");
    

    这将为您提供一个与您的字符串匹配的模式,并将文本放在第一组的方括号内。请查看Pattern API Documentation 了解更多信息。

    要提取字符串,您可以使用以下内容:

    Matcher m = MY_PATTERN.matcher("FOO[BAR]");
    while (m.find()) {
        String s = m.group(1);
        // s now contains "BAR"
    }
    

    【讨论】:

    • 值得一提的是,如果方括号之间有换行符,这将失败,您应该使用 Pattern.DOTALL 标志来避免这种情况。
    • 使用上面的模式,你将如何使用它来提取包含字符串 BAR 的字符串?我正在查看 Pattern API 和 Matcher API,但我仍然不确定如何获取字符串本身。
    • @cletus:好电话! @digiarnie:我在答案中添加了一个修订版,其中包含一些用于获得匹配的稻草人代码。
    【解决方案2】:

    非正则表达式:

    String input = "FOO[BAR]", extracted;
    extracted = input.substring(input.indexOf("["),input.indexOf("]"));
    

    或者,为了更好的性能/内存使用(感谢 Hosam):

    String input = "FOO[BAR]", extracted;
    extracted = input.substring(input.indexOf('['),input.lastIndexOf(']'));
    

    【讨论】:

    • 我会改用lastIndexOf(']'),它可以处理嵌套的括号。此外,我相信使用indexOf(char) 会比indexOf(String) 更快。
    • 不客气。您对性能的说明也非常相关,因为lastIndexOf 肯定会更快地找到右括号。
    • 什么更快,indexof substring etc etc or regexp?
    • 在下面查看 Amit 的“extracted”值:input.indexOf('[') + 1
    【解决方案3】:

    这是一个工作示例:

    RegexpExample.java

    package org.regexp.replace;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class RegexpExample
    {
        public static void main(String[] args)
        {
            String string = "var1[value1], var2[value2], var3[value3]";
            Pattern pattern = Pattern.compile("(\\[)(.*?)(\\])");
            Matcher matcher = pattern.matcher(string);
    
            List<String> listMatches = new ArrayList<String>();
    
            while(matcher.find())
            {
                listMatches.add(matcher.group(2));
            }
    
            for(String s : listMatches)
            {
                System.out.println(s);
            }
        }
    }
    

    它显示:

    value1
    value2
    value3
    

    【讨论】:

      【解决方案4】:
      import java.util.*;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      
      public static String get_match(String s, String p) {
          // returns first match of p in s for first group in regular expression 
          Matcher m = Pattern.compile(p).matcher(s);
          return m.find() ? m.group(1) : "";
      }
      
      get_match("FOO[BAR]", "\\[(.*?)\\]")  // returns "BAR"
      
      public static List<String> get_matches(String s, String p) {
          // returns all matches of p in s for first group in regular expression 
          List<String> matches = new ArrayList<String>();
          Matcher m = Pattern.compile(p).matcher(s);
          while(m.find()) {
              matches.add(m.group(1));
          }
          return matches;
      }
      
      get_matches("FOO[BAR] FOO[CAT]", "\\[(.*?)\\]")) // returns [BAR, CAT]
      

      【讨论】:

        【解决方案5】:

        如果您只需要获取[] 之间的任何内容,您可以像这样使用\[([^\]]*)\]

        Pattern regex = Pattern.compile("\\[([^\\]]*)\\]");
        Matcher m = regex.matcher(str);
        if (m.find()) {
            result = m.group();
        }
        

        如果您需要它的格式为 identifier + [ + content + ],那么您可以限制仅在标识符为字母数字时提取内容:

        [a-zA-Z][a-z-A-Z0-9_]*\s*\[([^\]]*)\]
        

        这将验证 Foo [Bar]myDevice_123["input"] 等内容。

        主要问题

        主要问题是当你想提取这样的内容时:

        FOO[BAR[CAT[123]]+DOG[FOO]]
        

        正则表达式不起作用,将返回 BAR[CAT[123FOO
        如果我们将正则表达式更改为\[(.*)\],那么我们就可以了,但是,如果您尝试从更复杂的内容中提取内容,例如:

        FOO[BAR[CAT[123]]+DOG[FOO]] = myOtherFoo[BAR[5]]
        

        所有正则表达式都不起作用。

        在所有情况下提取正确内容的最准确正则表达式会复杂得多,因为它需要平衡 [] 对并为您提供内容。

        更简单的解决方案

        如果您的问题变得复杂并且[] 的内容任意,您可以平衡[] 对并使用普通旧代码而不是正则表达式提取字符串:

        int i;
        int brackets = 0;
        string c;
        result = "";
        for (i = input.indexOf("["); i < str.length; i++) {
            c = str.substring(i, i + 1);
            if (c == '[') {
                brackets++;
            } else if (c == ']') {
                brackets--;
                if (brackets <= 0) 
                    break;
            }
            result = result + c;
        }   
        

        这更像是伪代码而不是真实代码,我不是 Java 编码器,所以我不知道语法是否正确,但应该很容易改进。
        重要的是这段代码应该可以工作并允许您提取[] 的内容,不管它有多复杂。

        【讨论】:

          【解决方案6】:

          我认为你的正则表达式看起来像:

          /FOO\[(.+)\]/
          

          假设 FOO 将保持不变。

          所以,把它放在 Java 中:

          Pattern p = Pattern.compile("FOO\\[(.+)\\]");
          Matcher m = p.matcher(inputLine);
          

          【讨论】:

          • FOO[BAR] FOO[BAZ] -> 使用正则表达式将返回:"BAR] FOO[BAZ"
          【解决方案7】:
          String input = "FOO[BAR]";
          String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));
          

          这将返回第一个'['和最后一个']'之间的值

          Foo[Bar] => 酒吧

          Foo[Bar[test]] => Bar[test]

          注意:如果输入字符串格式不正确,您应该添加错误检查。

          【讨论】:

            【解决方案8】:

            假设在 /FOO\[([^\]]*)\]/ 中不允许使用其他右方括号

            【讨论】:

              【解决方案9】:

              我会定义我想要[] 之间的最大非] 字符数。这些需要用反斜杠转义(在Java中,这些需要再次转义),并且非]的定义是一个字符类,因此在[]中(即[^\\]])。结果:

              FOO\\[([^\\]]+)\\]
              

              【讨论】:

                【解决方案10】:

                如果你想解析一些来自 mYearInDB.toString() =[2013] 的字符串,它会像这样工作,它会给出 2013

                Matcher n = MY_PATTERN.matcher("FOO[BAR]"+mYearInDB.toString());
                while (n.find()) {
                 extracredYear  = n.group(1);
                 // s now contains "BAR"
                    }
                    System.out.println("Extrated output is : "+extracredYear);
                

                【讨论】:

                  【解决方案11】:

                  这个正则表达式对我有用:

                  form\[([^']*?)\]
                  

                  示例:

                  form[company_details][0][name]
                  form[company_details][0][common_names][1][title]
                  

                  输出:

                  Match 1
                  1.  company_details
                  Match 2
                  1.  company_details
                  

                  http://rubular.com/上测试

                  【讨论】:

                    【解决方案12】:
                    "FOO[DOG]".replaceAll("^.*?\\[|\\].*", "");
                    

                    这将返回一个字符串 只取方括号内的字符串。

                    这会从方括号中删除所有字符串。

                    您可以在线测试此 java 示例代码: http://tpcg.io/wZoFu0

                    您可以从这里测试这个正则表达式: https://regex101.com/r/oUAzsS/1

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-05-12
                      • 2012-12-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多