Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用于分隔括号中的字符串的正则表达式_Java_Regex_String - Fatal编程技术网

Java 用于分隔括号中的字符串的正则表达式

Java 用于分隔括号中的字符串的正则表达式,java,regex,string,Java,Regex,String,我有一个字符串,其中包含2或3个公司名称,每个名称用括号括起来。每个公司名称也可以包含括号中的单词。我需要用正则表达式将它们分开,但没有找到如何分开的方法 我的输入str: (Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.)) (Motorsport racing Ltd.) or (Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.)) 预期结果是: str1 = Motor

我有一个
字符串
,其中包含2或3个公司名称,每个名称用括号括起来。每个公司名称也可以包含括号中的单词。我需要用正则表达式将它们分开,但没有找到如何分开的方法

我的
输入str

(Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.)) (Motorsport racing Ltd.)
or 
(Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.))
预期结果是:

str1 = Motor (Sport) (racing) Ltd.
str2 = Motorsport racing (Ltd.)
str3 = Motorsport racing Ltd.
我的代码:

String str1, str2, str3;
Pattern p = Pattern.compile("\\((.*?)\\)");
Matcher m = p.matcher(inputStr);
int index = 0;
while(m.find()) {

    String text = m.group(1);
    text = text != null && StringUtils.countMatches(text, "(") != StringUtils.countMatches(text, ")") ? text + ")" : text;

    if (index == 0) {
        str1= text;
    } else if (index == 1) {
        str2 = text;
    } else if (index == 2) {
        str3 = text;
    }

    index++;
}
这适用于
str2
str3
,但不适用于
str1

当前结果:

str1 = Motor (Sport)
str2 = Motorsport racing (Ltd.)
str3 = Motorsport racing Ltd.

你可以不用正则表达式解决这个问题;关于这个问题,请参考

以下是一个例子:

import java.util.Stack;

public class Main {

    public static void main(String[] args) {
        String input = "(Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.)) (Motorsport racing Ltd.)";
        for (int index = 0; index < input.length(); ) {
            if (input.charAt(index) == '(') {
                int close = findClose(input, index);  // find the  close parentheses
                System.out.println(input.substring(index + 1, close));
                index = close + 1;  // skip content and nested parentheses
            } else {
                index++;
            }
        }
    }
    private static int findClose(String input, int start) {
        Stack<Integer> stack = new Stack<>();
        for (int index = start; index < input.length(); index++) {
            if (input.charAt(index) == '(') {
                stack.push(index);
            } else if (input.charAt(index) == ')') {
                stack.pop();
                if (stack.isEmpty()) {
                    return index;
                }
            }
        }
        // unreachable if your parentheses is balanced
        return 0;
    }

}

所以我们可以假设括号最多可以嵌套两层。所以我们可以不用太多魔法就可以做到。我将使用以下代码:

List<String> matches = new ArrayList<>();
Pattern p = Pattern.compile("\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)");
Matcher m = p.matcher(inputStr);
while (m.find()) {
    String fullMatch = m.group();
    matches.add(fullMatch.substring(1, fullMatch.length() - 1));
}
List matches=new ArrayList();
Pattern p=Pattern.compile(“\\([^()]*(?:\\([^()]*\\)[^()]*)*\)”;
匹配器m=p.Matcher(inputStr);
while(m.find()){
字符串fullMatch=m.group();
add(fullMatch.substring(1,fullMatch.length()-1));
}
说明:

  • 首先我们匹配一个括号:
    \\(
  • 然后我们匹配一些非括号字符:[^()]*
  • 然后零次或多次:
    (?:…)*
    我们将看到括号内的一些内容,然后是一些非括号:
  • \\([^()]*\\)[^()]*
    -重要的是,我们不允许在括号内再插入任何括号
  • 然后右括号出现:
    \\)
  • m.group()返回实际的完全匹配
  • fullMatch.substring(1,fullMatch.length()-1)
    删除开头和结尾的括号。你也可以和另一组人一起做。我只是不想让正则表达式更难看

我看到每个左括号都有一个右括号,我看不到出现嵌套括号的任何可能性。因此,使用不嵌套的平衡圆括号会导致这样的正则表达式:

\(((?:[^()]*|\([^)]*\))*)\)
您只需要有权访问第一个捕获组

细分

  • \(
    匹配左括号
    • 开始捕获组1
      • (?:
        非捕获组1的开始
        • [^()]*
          匹配设置中/未设置的字符,可选
        • |
        • \([^\)]*\)
          匹配括号组
      • )*
        尽可能多,结束非捕获组1
    • 捕获组1结束
  • \)
    匹配右括号

    • 为什么不使用堆栈来解决它呢?它将只有O(n)复杂度

    • 只要解析字符串,每次遇到
      ”(“
      ”,将其推到堆栈中,每次遇到
      ”)
      ,都会从堆栈中弹出。 否则,将字符放入缓冲区
    • 如果在按下
      ”(“
      时堆栈为空,则表示它位于公司名称中,因此也将其放入缓冲区
    • 类似地,如果堆栈在弹出后不是空的,则将
      “)”
      放在缓冲区中,因为它是公司名称的一部分
    • 如果弹出后堆栈为空,则表示第一个公司名称已结束,缓冲区值为公司名称并清除缓冲区

      String string = "(Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.)) (Motorsport racing Ltd.)";
      List<String> result = new ArrayList();
      StringBuffer buffer = new StringBuffer();
      
      Stack<Character> stack = new Stack<Character>();
      for (int j = 0; j < string.length(); j++) {
          if (string.charAt(j) == '(') {
              if (!stack.empty())
                  buffer.append('(');
              stack.push('(');
          } else if (string.charAt(j) == ')') {
              stack.pop();
              if (stack.empty()) {
                  result.add(buffer.toString());
                  buffer = new StringBuffer();
              }else
                  buffer.append(')');
          }else{
              buffer.append(string.charAt(j));
          }
      }
      
      for(int i=0;i<result.size();i++){
          System.out.println(result.get(i));
      }
      
      String=“(汽车(运动)(赛车)有限公司)(汽车运动赛车(有限公司)(赛车有限公司)”;
      列表结果=新建ArrayList();
      StringBuffer=新的StringBuffer();
      堆栈=新堆栈();
      对于(int j=0;j对于(int i=0;我可以告诉我们更多关于输入的信息吗?例如,我可以看到公司信息以
      (有限公司)
      Ltd结尾。
      总是设置在那里还是可以更改?请尝试
      \(((?:[^()]+\124;\([^\]*\)*)\
      。实时演示(右侧匹配):你不应该对嵌套结构使用正则表达式。但如果你真的必须这样做,请看这里:@ErwinBolwidt你认为有必要匹配问题中的嵌套括号吗?@revo你不认为吗?-1这最多应该是一个注释,将其视为另一种方法的建议。用“使用方法B”回答问题“我需要方法a的帮助”是不正确的在错误的意义上有帮助removal@ifloop即使方法B在语法层面上比方法A更有效?@ifloop,你是对的。关于解决问题的方法,我不同意。其他方法是有用的。你可能想检查一下这篇不受欢迎的元帖子:@ifloop你是对的,除了OP会提到我的部分f他不想要任何不同的方法。对一个问题采取不同的方法可以拓宽你的视野,帮助你更好地理解这个问题。如果这种替代方法不能解决老年退休金问题,那么他可以很容易地提到这一点作为回应。-1这应该是一个评论,将其视为对不同方法的建议。回答问题n“我需要方法A的帮助”与“使用方法B”在消除错误的意义上没有帮助(参见刘能回答的评论)@ifloop很酷,你解释了你的-1。但是,这种评论和-1-s让人觉得很不受欢迎。我认为可以发布开箱即用的答案。有时这些是流行的答案,即OP想用正则表达式解析xml时。因为你唯一推到堆栈中的是
      (“
      ,您不需要真正的堆栈,只需要一个
      int depth
      来跟踪堆栈深度,即未闭合括号的数量。@Boann您是对的。我当时没有想到。您
      String string = "(Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.)) (Motorsport racing Ltd.)";
      List<String> result = new ArrayList();
      StringBuffer buffer = new StringBuffer();
      
      Stack<Character> stack = new Stack<Character>();
      for (int j = 0; j < string.length(); j++) {
          if (string.charAt(j) == '(') {
              if (!stack.empty())
                  buffer.append('(');
              stack.push('(');
          } else if (string.charAt(j) == ')') {
              stack.pop();
              if (stack.empty()) {
                  result.add(buffer.toString());
                  buffer = new StringBuffer();
              }else
                  buffer.append(')');
          }else{
              buffer.append(string.charAt(j));
          }
      }
      
      for(int i=0;i<result.size();i++){
          System.out.println(result.get(i));
      }