我有一个String
,其中包含2或3个公司名称,每个名称都括在括号中。每个公司名称也可以包含括号中的单词。我需要使用正则表达式将它们分开,但是没有找到。
我的inputStr
:
(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.
答案 0 :(得分:9)
你可以在没有正则表达式的情况下解决这个问题;请参阅有关how to find the outermost parentheses的问题。
以下是一个例子:
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;
}
}
输出:
Motor (Sport) (racing) Ltd.
Motorsport racing (Ltd.)
Motorsport racing Ltd.
答案 1 :(得分:7)
因此我们可以假设括号最多可以嵌套两个级别。所以我们可以毫不费力地做到这一点。我会使用这段代码:
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)
从开头和结尾删除括号。你也可以和另一个团队一起做。我只是不想让正则表达式更加丑陋。答案 2 :(得分:6)
为什么不用堆栈解决它?它只有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));
}
答案 3 :(得分:4)
我看到每个左括号都有一个结束对应物,我没有看到嵌套括号发生的任何可能性。因此,没有嵌套的括号的平衡括号会产生这样的正则表达式:
\(((?:[^()]*|\([^)]*\))*)\)
您只需拥有第一个捕获组的访问权限。
<强>击穿强>:
\(
匹配左括号
(
开始捕获第1组
(?:
开始非捕获组1
[^()]*
匹配未设置的字符,可选|
或\([^\)]*\)
匹配括号组)*
尽可能地结束非捕获组1 )
结束捕获第1组\)
匹配右括号