【问题标题】:Regex to capture unpaired brackets or parentheses正则表达式捕获不成对的括号或括号
【发布时间】:2020-02-21 08:44:46
【问题描述】:

正如标题所示,我如何使用正则表达式捕获不成对的括号或括号,准确地说,在java中,对于java来说是新手。例如,假设我有下面的字符串;

Programming is productive, (achieving a lot, and getting good results), it is often 1) demanding and 2) costly.

如何捕获 1) 和 2)。 我试过了:

([^\(\)][\)])

但是,我得到的结果包括如下的 s),而不是 1) 和 2):

s), 1) and 2)

我检查了链接:Regular expression to match balanced parentheses,但是,这个问题似乎是指递归或嵌套结构,这与我的情况完全不同。 我的情况是匹配右括号或右括号,以及没有关联左括号或括号的任何关联文本。

【问题讨论】:

  • Regular expression to match balanced parentheses 的可能重复项。正则表达式不是这项工作的正确工具,但它可以通过递归正则表达式来完成——第三个投票最多的答案中有一个 Java 部分。
  • 我认为 OP 不想匹配平衡括号。他们想要匹配右括号或右括号,以及没有关联左括号或括号的任何关联文本。
  • @WJS,确切的情况或期望的结果。
  • @DerickMarfo 我有一个解决方案,但不是regex,所以我没有发布它。它使用一个简单的堆栈并跟踪括号。
  • @ggorlen 很抱歉回复晚了,但是,对于任意嵌套的括号,我相信下面会为任意嵌套括号的完整外部组完成工作:(?=\()(?:(?=.*?\((?!.*?\1)(.*\)(?!.*\2).*))(?=.*?\)(?!.*?\2)(.*)).)+?.*?(?=\1)[^(]*(?=\2$) 和以下匹配内部组太:(?=\()(?=((?:(?=.*?\((?!.*?\2)(.*\)(?!.*\3).*))(?=.*?\)(?!.*?\3)(.*)).)+?.*?(?=\2)[^(]*(?=\3$)))。借自此博客:[drregex.com/2017/11/match-nested-brackets-with-regex-new.html]

标签: java regex match parentheses brackets


【解决方案1】:

也许,

\b\d+\)

我猜可能只是返回所需的输出。

Demo 1

另一种方法是查看您可能拥有的左边界,在这种情况下,我看到数字,然后在右大括号之前我们还有什么其他字符,然后我们可以设计一些其他简单的表达式,类似于:

\b\d[^)]*\) 

Demo 2

测试

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegularExpression{

    public static void main(String[] args){

        final String regex = "\\b\\d[^)]*\\)";
        final String string = "Programming is productive, (achieving a lot, and getting good results), it is often 1) demanding and 2) costly.\n\n"
             + "Programming is productive, (achieving a lot, and getting good results), it is often 1a b) demanding and 2a a) costly.\n\n\n"
             + "Programming is productive, (achieving a lot, and getting good results), it is often 1b) demanding and 2b) costly.\n\n"
             + "It is not supposed to match ( s s 1) \n";

        final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        final Matcher matcher = pattern.matcher(string);

        while (matcher.find()) {
            System.out.println("Full match: " + matcher.group(0));
            for (int i = 1; i <= matcher.groupCount(); i++) {
                System.out.println("Group " + i + ": " + matcher.group(i));
            }
        }


    }
}

输出

Full match: 1)
Full match: 2)
Full match: 1a b)
Full match: 2a a)
Full match: 1b)
Full match: 2b)
Full match: 1)

正则表达式电路

jex.im 可视化正则表达式:

【讨论】:

  • 它不应该匹配( s s 1),因为右括号有一个伴侣。
  • @Emma 谢谢!!!你真是个天才。我真是太棒了。你真的很有帮助,因为过去几个小时我一直在谷歌上搜索,但没有找到我的解决方案。我相信你拯救了很多像我一样的人!再次感谢了不起的程序员!
【解决方案2】:

这不是一个正则表达式解决方案(显然),但我想不出一个好方法来做到这一点。这只是使用堆栈来跟踪括号。

对于输入字符串"(*(**)**) first) second) (**) (*ksks*) third) ** fourth)( **)

打印出来

首先)
第二)
第三)
第四)

所有其他括号都被忽略,因为它们是匹配的。

      String s =
            "(*(**)**) first) second) (**) (*ksks*) third) ** fourth)( **)";
      Pattern p;
      List<String> found = new ArrayList<>();
      Stack<Character> tokens = new Stack<>();
      int pcount = 0;

      for (char c : s.toCharArray()) {
         switch (c) {
            case ' ':
               tokens.clear();
               break;
            case '(':
               pcount++;
               break;
            case ')':
               pcount--;
               if (pcount == -1) {
                  String v = ")";
                  while (!tokens.isEmpty()) {
                     v = tokens.pop() + v;
                  }
                  found.add(v);
                  pcount = 0;
               }
               break;
            default:
               tokens.push(c);
         }
      }
      found.forEach(System.out::println);

注意:将括号 (]) 集成到上面将是一个挑战(尽管并非不可能),因为需要检查诸如 ( [ ) ] 之类的构造,其中不清楚如何解释它。这就是为什么在指定此类要求时需要准确说明它们的原因。

【讨论】:

  • 这是非常正确的想法。但是,这仅在第一级递归上检测到不匹配的括号。 "(*(**)first) **)",我们得到错误的输出,因为我们不知道意图是匹配 first)。 OP 的示例是一个微不足道的案例,我认为 OP 需要进一步澄清我们需要检测的内容(即我们如何区分不匹配的嵌套组?按数字?)。
  • @ggorlen 我想要实现的只是捕获不平衡的括号,而不是平衡的集合。因此,应该捕获 1)、a)、e),但是,如果在同一字符串中可用,则不应捕获 (3 和 4)、(2,8)、(hello world) 等。半括号不一定是嵌套的。
  • @ggorlen 首先感谢您的回复,但是,根据您的示例,"(foo 1) bar)",我只需要"bar)",而不需要"1)"。所以,我相信你现在明白我的意思了。
  • 好的,那么这是最好的答案。感谢您的澄清。
  • @ggorlen 也感谢您的理解
猜你喜欢
  • 1970-01-01
  • 2015-01-20
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 2013-06-17
  • 2012-04-13
  • 2020-04-27
  • 1970-01-01
相关资源
最近更新 更多