首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分隔括在括号中的字符串的正则表达式

分隔括在括号中的字符串的正则表达式
EN

Stack Overflow用户
提问于 2018-05-08 09:58:42
回答 4查看 1.1K关注 0票数 10

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

我的inputStr

代码语言:javascript
复制
(Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.)) (Motorsport racing Ltd.)
or 
(Motor (Sport) (racing) Ltd.) (Motorsport racing (Ltd.))

预期结果是:

代码语言:javascript
复制
str1 = Motor (Sport) (racing) Ltd.
str2 = Motorsport racing (Ltd.)
str3 = Motorsport racing Ltd.

我的代码:

代码语言:javascript
复制
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++;
}

这对于str2str3非常有用,但对str1却不起作用。

目前的结果:

代码语言:javascript
复制
str1 = Motor (Sport)
str2 = Motorsport racing (Ltd.)
str3 = Motorsport racing Ltd.
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-05-08 10:19:07

因此,我们可以假设括号最多可以嵌套在两个层次的深度。所以我们不需要太多的魔法就能做到。我会用下面的代码:

代码语言:javascript
复制
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));
}

解释:

  • 首先,我们匹配一个括号:\\(
  • 然后我们匹配一些非括号字符:^()*
  • 然后是零次或多次:(?:...)*,我们将在括号中看到一些内容,然后再次看到一些非括号:
  • \\([^()]*\\)[^()]* -重要的是我们不允许更多的括号在里面的括号
  • 然后是结束括号:\\)
  • m.group();返回实际的完全匹配。
  • fullMatch.substring(1, fullMatch.length() - 1)从开头和结尾删除括号。你也可以和另一个小组一起做。我只是不想让裁判更丑。
票数 7
EN

Stack Overflow用户

发布于 2018-05-08 10:12:57

您可以不用regex来解决这个问题;请参考有关how to find the outermost parentheses的这个问题。

下面是一个示例:

代码语言:javascript
复制
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;
    }

}

输出:

代码语言:javascript
复制
Motor (Sport) (racing) Ltd.
Motorsport racing (Ltd.)
Motorsport racing Ltd.
票数 9
EN

Stack Overflow用户

发布于 2018-05-08 10:30:22

为什么不直接用堆栈来解决呢?它只具有O(n)复杂度

  1. 只需解析字符串,每次遇到'('时,将其推送到堆栈中,每次遇到')'时,就从堆栈中弹出。否则,将字符放入缓冲区。
  2. 如果堆栈在推送'('时是空的,那就意味着它在公司名称中,所以也要放在缓冲区中。
  3. 类似地,如果堆栈在弹出后不是空的,那么将')'放在缓冲区中,因为它是公司名称的一部分。
  4. 如果堆栈在弹出后为空,这意味着第一个公司名称已经结束,而缓冲区值是公司的名称,并清除缓冲区。 String =“(汽车(运动)(赛车)有限公司)(赛车(有限公司))(赛车比赛有限公司)“;列表结果=新ArrayList();StringBuffer缓冲器=新StringBuffer();堆栈=新堆栈();for (int j= 0;j< string.length();j++) { if (string.charAt(j) == '(') { if (!stack.empty()buffer.append(‘(’‘);stack.push(’(‘));} if (string.charAt(j) == ')') { stack.pop();if (stack.empty()) { result.add(buffer.toString());缓冲器=新StringBuffer();}stack.empty buffer.append(')');}stack.empty{buffer.append(string.charAt(J);}} for(int i=0);i
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50230897

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档