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结束)
匹配右括号\)
- 只要解析字符串,每次遇到
”,将其推到堆栈中,每次遇到”(“
,都会从堆栈中弹出。 否则,将字符放入缓冲区”)
- 如果在按下
时堆栈为空,则表示它位于公司名称中,因此也将其放入缓冲区”(“
- 类似地,如果堆栈在弹出后不是空的,则将
放在缓冲区中,因为它是公司名称的一部分“)”
- 如果弹出后堆栈为空,则表示第一个公司名称已结束,缓冲区值为公司名称并清除缓冲区
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结尾。
。实时演示(右侧匹配):你不应该对嵌套结构使用正则表达式。但如果你真的必须这样做,请看这里:@ErwinBolwidt你认为有必要匹配问题中的嵌套括号吗?@revo你不认为吗?-1这最多应该是一个注释,将其视为另一种方法的建议。用“使用方法B”回答问题“我需要方法a的帮助”是不正确的在错误的意义上有帮助removal@ifloop即使方法B在语法层面上比方法A更有效?@ifloop,你是对的。关于解决问题的方法,我不同意。其他方法是有用的。你可能想检查一下这篇不受欢迎的元帖子:@ifloop你是对的,除了OP会提到我的部分f他不想要任何不同的方法。对一个问题采取不同的方法可以拓宽你的视野,帮助你更好地理解这个问题。如果这种替代方法不能解决老年退休金问题,那么他可以很容易地提到这一点作为回应。-1这应该是一个评论,将其视为对不同方法的建议。回答问题n“我需要方法A的帮助”与“使用方法B”在消除错误的意义上没有帮助(参见刘能回答的评论)@ifloop很酷,你解释了你的-1。但是,这种评论和-1-s让人觉得很不受欢迎。我认为可以发布开箱即用的答案。有时这些是流行的答案,即OP想用正则表达式解析xml时。因为你唯一推到堆栈中的是\(((?:[^()]+\124;\([^\]*\)*)\
,您不需要真正的堆栈,只需要一个(“
来跟踪堆栈深度,即未闭合括号的数量。@Boann您是对的。我当时没有想到。您int depth
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)); }
- 为什么不使用堆栈来解决它呢?它将只有O(n)复杂度