当前位置: 首页 > 面试题库 >

正则表达式删除嵌套括号

洪楷
2023-03-14
问题内容

我一直试图在Java中编写一个正则表达式以删除下面括号中的所有内容,同时保留其他所有内容。 注意,括号可以嵌套,这就是为什么我的模式失败的原因
。有人能帮我吗?下面我试过了:

    String testData =
            "1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. dxe5 dxe5 8. Qxd8 Rxd8 9. Bg5 Nbd7 10. O-O-O {Diagram [#]} " +
            "Rf8 (10... Re8 11. Nb5 (11. Nd5)) (10... h6 11. Bxf6 Bxf6 12. Nd5) 11. Nd5 c6 (11... Nxe4 12. Nxc7 Rb8 13. Be3 b6 ) 12. Ne7+ Kh8 13. " +
            "Nxc8 Raxc8 14. Bxf6 (14. Be3) 14... Nxf6 15. Nd2 (15. Bd3) 15... Bh6 16. f3 Nd7 17. Kc2 Bxd2 (17... Rcd8 18. b4) 18. Rxd2 Nc5 19. b4 Ne6 20. Rd7 b5 " +
            "(20... Rcd8 21. Rxb7 Nd4+ 22. Kd3) 21. Rxa7 Nd4+ 22. Kd3 Rcd8 23. Ke3 Nc2+ 24. Kf2 Rd2 25. Rd1 Rfd8 26. Rxd2 {Diagram [#]} (26. cxb5 cxb5 " +
            "27. Rc7 Rxd1 28. Bxd1 Rd2+ 29. Kg3 Ne1 30. Bb3 f6 31. Rf7 Nxg2 32. Rf8+ Kg7 33. Rf7+ Kh6 34. Rxf6 Nf4 35. Kh4 (35. Rxf4 exf4+ 36. Kxf4 Rxh2) 35... " +
            "Rxh2+ 36. Kg4 Rg2+ 37. Kh4 Nd3 38. a3 Rh2+ 39. Kg4 Rh1 40. Rc6 {Diagram [#]}) 26... Rxd2 27. Kf1 Nd4 28. cxb5 cxb5 29. a4 (29. Rd7 Rxa2 30. Bd3 Ra3 31. " +
            "Be2 Ra1+ 32. Kf2 Ra2 ) (29. Bxb5 Nxb5) 29... Rxe2 (29... bxa4 30. Bc4) 30. axb5 Rb2 31. b6 Rxb4 32. b7 Kg7  ";


    testData = testData.replaceAll(Pattern.quote("{") + ".*" + Pattern.quote("}"), "")
                    .replaceAll(Pattern.quote("(") + ".*" + Pattern.quote(")"), "")
                    .replaceAll(Pattern.quote("$") + "[0-9]+", "");

    System.out.println(testData);

但这打印:

  1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 OO 6. Be2 e5 7. dxe5 dxe5 8. Qxd8 Rxd8 9. Bg5 Nbd7 10. OOO Rf8)11. Nd5 c6 12. Ne7 + Kh8 13. Nxc8 Raxc8 14. Bxf6 14 … Nxf6 15. Nd2 15 … Bh6 16. f3 Nd7 17. Kc2 Bxd2 18. Rxd2 Nc5 19. b4 Ne6 20. Rd7 b5 21. Rxa7 Nd4 + 22.Kd3 Rcd8 23. Ke3 Nc2 + 24 。Kf2 Rd2 25. Rd1 Rfd8 26. Rxd2 35 … Rxh2 + 36. Kg4 Rg2 + 37. Kh4 Nd3 38. a3 Rh2 + 39. Kg4 Rh1 40.Rc6)26 … Rxd2 27. Kf1 Nd4 28. cxb5 cxb5 29。 a4 29 … Rxe2 30. axb5 Rb2 31. b6 Rxb4 32. b7 Kg7

这显然是错误的,因为它带有括号。

正确的答案是:

  1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 OO 6. Be2 e5 7. dxe5 dxe5 8. Qxd8 Rxd8 9. Bg5 Nbd7 10. OOO Rf8 11. Nd5 c6 12. Ne7 + Kh8 13. Nxc8 Raxc8 14. Bxf6 14 … Nxf6 15. Nd2 15 … Bh6 16. f3 Nd7 17. Kc2 Bxd2 18. Rxd2 Nc5 19. b4 Ne6 20. Rd7 b5 21. Rxa7 Nd4 + 22. Kd3 Rcd8 23. Ke3 Nc2 + 24。 Kf2 Rd2 25.Rd1 Rfd8 26.Rxd2 26 … Rxd2 27.Kf1 Nd4 28.cxb5 cxb5 29.a4 29 … Rxe2 30.axb5 Rb2 31.b6 Rxb4 32.b7 Kg7

问题答案:

不要在这里使用正则表达式。从示例中您可以看到,类似的东西\\(.*?)\\)会尝试在首次建立(和下一个之间找到最小的匹配,)因此在诸如

a (b (c d) e) f

正则表达式\(.*?\)将匹配

a (b (c d) e) f
  ^^^^^^^^

并且将留下e)无与伦比的部分。

您可能可以为此任务编写正则表达式,因为某些正则表达式类型支持递归,但不幸的是,Java中使用的正则表达式引擎不支持。

因此,要删除嵌套的括号,您可以编写自己的简单解析器,例如
(我假设文本格式正确,所以没有类似({)}或未封闭的括号之类的东西)

String data = "1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. dxe5 dxe5 8. Qxd8 Rxd8 9. Bg5 Nbd7 10. O-O-O {Diagram [#]} "
        + "Rf8 (10... Re8 11. Nb5 (11. Nd5)) (10... h6 11. Bxf6 Bxf6 12. Nd5) 11. Nd5 c6 (11... Nxe4 12. Nxc7 Rb8 13. Be3 b6 ) 12. Ne7+ Kh8 13. "
        + "Nxc8 Raxc8 14. Bxf6 (14. Be3) 14... Nxf6 15. Nd2 (15. Bd3) 15... Bh6 16. f3 Nd7 17. Kc2 Bxd2 (17... Rcd8 18. b4) 18. Rxd2 Nc5 19. b4 Ne6 20. Rd7 b5 "
        + "(20... Rcd8 21. Rxb7 Nd4+ 22. Kd3) 21. Rxa7 Nd4+ 22. Kd3 Rcd8 23. Ke3 Nc2+ 24. Kf2 Rd2 25. Rd1 Rfd8 26. Rxd2 {Diagram [#]} (26. cxb5 cxb5 "
        + "27. Rc7 Rxd1 28. Bxd1 Rd2+ 29. Kg3 Ne1 30. Bb3 f6 31. Rf7 Nxg2 32. Rf8+ Kg7 33. Rf7+ Kh6 34. Rxf6 Nf4 35. Kh4 (35. Rxf4 exf4+ 36. Kxf4 Rxh2) 35... "
        + "Rxh2+ 36. Kg4 Rg2+ 37. Kh4 Nd3 38. a3 Rh2+ 39. Kg4 Rh1 40. Rc6 {Diagram [#]}) 26... Rxd2 27. Kf1 Nd4 28. cxb5 cxb5 29. a4 (29. Rd7 Rxa2 30. Bd3 Ra3 31. "
        + "Be2 Ra1+ 32. Kf2 Ra2 ) (29. Bxb5 Nxb5) 29... Rxe2 (29... bxa4 30. Bc4) 30. axb5 Rb2 31. b6 Rxb4 32. b7 Kg7  ";

StringBuilder buffer = new StringBuilder();

int parenthesisCounter = 0;

for (char c : data.toCharArray()) {
    if (c == '(' || c == '{' )
        parenthesisCounter++;
    if (c == ')' || c == '}' )
        parenthesisCounter--;
    if (!(c == '(' || c == '{' || c == ')' || c == '}') && parenthesisCounter == 0)
        buffer.append(c);
}

之后,您可以像以前一样集中精力删除其余不需要的数据

.replaceAll(Pattern.quote("$") + "[0-9]+", "");

这样的结果

System.out.println(buffer.toString().replaceAll(
        Pattern.quote("$") + "[0-9]+", ""));

将会

1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. dxe5 dxe5 8. Qxd8 Rxd8 9. Bg5 Nbd7 10. O-O-O Rf8 11. Nd5 c6 12. Ne7+ Kh8 13. Nxc8 Raxc8 14. Bxf6 14... Nxf6 15. Nd2 15... Bh6 16. f3 Nd7 17. Kc2 Bxd2 18. Rxd2 Nc5 19. b4 Ne6 20. Rd7 b5 21. Rxa7 Nd4+ 22. Kd3 Rcd8 23. Ke3 Nc2+ 24. Kf2 Rd2 25. Rd1 Rfd8 26. Rxd2 26... Rxd2 27. Kf1 Nd4 28. cxb5 cxb5 29. a4 29... Rxe2 30. axb5 Rb2 31. b6 Rxb4 32. b7 Kg7



 类似资料:
  • 我有这样一个文本: 我试图在c#中使用正则表达式来提取嵌套的if/eles-段。 要查找“?”,我使用了: 模式1: 找到“:”我用了: 模式2:

  • 正如标题所说,以下是一个输入示例: 当然,匹配的字符串将通过递归进行处理。 我希望第一个递归匹配: 之后的过程不用说。。。

  • 我想将带有嵌套大括号的原始字符串解析为多维数组。下面我添加了一些有效的示例代码。但主要问题是,我的正则表达式只捕获第一个匹配的组,而忽略了另一个发生。 非常感谢您的帮助。 代码: 原始字符串(data.txt): 代码输出: 但例外输出:

  • 问题内容: 我正在尝试匹配带有嵌套括号的类似数学表达式的字符串。 [‘((((1 + 0)+1)+1)’] 我希望它与所有包含的表达式匹配,例如(1 + 0),((1 + 0)+1)… 我什至不在乎它是否匹配不需要的表达式,例如(((1 + 0),我可以照顾的。 为什么它还没有这样做,我该怎么做? 问题答案: 正则表达式尝试匹配尽可能多的文本,从而消耗了所有字符串。它不会在字符串的一部分上寻找正则

  • 我有一个输入字符串,里面有括号,外面有双引号。这些括号可以嵌套。我想去掉只有在双引号外才有括号的字符串。 我尝试了这个正则表达式这将获取包含在圆括号内的所有内容,无论双引号内外。 我得到的实际输出是: 我预计产出为:

  • 问题内容: 我将如何编写一个正则表达式来删除所有以#开头并在该行结束处停止的注释-但同时要排除前两行,即 和 问题答案: 您可以通过使用解析Python代码来删除注释。以下是从docs对该示例进行的稍微修改的版本: 例如: 如果script.py包含 然后的输出是