Java Regex不匹配

时间:2015-10-28 21:43:34

标签: java regex

我正在尝试编写一个程序,该程序将返回\begin{theorem}\end{theorem}之间以及\begin{proof}\end{proof}之间的所有文字。

使用正则表达式似乎很自然,但因为有很多潜在的元字符,所以需要将它们转义。

这是我写的代码:

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

public class LatexTheoremProofExtractor {

    // This is the LaTeX source that will be processed
    private String source = null;

    // These are the list of theorems and proofs that are extracted, respectively 
    private ArrayList<String> theorems = null;
    private ArrayList<String> proofs = null;

    // These are the patterns to match theorems and proofs, respectively 
    private static final Pattern THEOREM_REGEX = Pattern.compile("\\begin\\{theorem\\}(.+?)\\end\\{theorem\\}");
    private static final Pattern PROOF_REGEX = Pattern.compile("\\begin\\{proof\\}(.+?)\\end\\{proof\\}");

    LatexTheoremProofExtractor(String source) {
        this.source = source;
    }

    public void parse() {
        extractEntity("theorem");
        extractEntity("proof");
    }

    private void extractTheorems() {
        if(theorems != null) {
            return;
        }

        theorems = new ArrayList<String>();

        final Matcher matcher = THEOREM_REGEX.matcher(source);
        while (matcher.find()) {
            theorems.add(new String(matcher.group(1)));
        }   
    }

    private void extractProofs() {
        if(proofs != null) {
            return;
        }

        proofs = new ArrayList<String>();

        final Matcher matcher = PROOF_REGEX.matcher(source);
        while (matcher.find()) {
            proofs.add(new String(matcher.group(1)));
        }       
    }

    private void extractEntity(final String entity) {   
        if(entity.equals("theorem")) {
            extractTheorems();
        } else if(entity.equals("proof")) {
            extractProofs();
        } else {
            // TODO: Throw an exception or something
        }       
    }

    public ArrayList<String> getTheorems() {
        return theorems;
    }

}

以下是我的测试失败

@Test 
public void testTheoremExtractor() {
    String source = "\\begin\\{theorem\\} Hello, World! \\end\\{theorem\\}";
    LatexTheoremProofExtractor extractor = new LatexTheoremProofExtractor(source);
    extractor.parse();
    ArrayList<String> theorems = extractor.getTheorems();
    assertEquals(theorems.get(0).trim(), "Hello, World!");
}

显然,我的测试表明我希望在这个测试中只有一场比赛,它应该是“Hello,World!” (修剪后)。

目前theorems是一个空的非null数组。因此我的Matcher与模式不匹配。谁能帮我理解为什么?

谢谢, erip

3 个答案:

答案 0 :(得分:1)

以下是您需要对代码进行的更新 - 提取器方法中的2个正则表达式应更改为

private static final Pattern THEOREM_REGEX = Pattern.compile(Pattern.quote("\\begin\\{theorem\\}") + "(.+?)" + Pattern.quote("\\end\\{theorem\\}"));
private static final Pattern PROOF_REGEX = Pattern.compile(Pattern.quote("\\begin\\{proof\\}") + "(.+?)" + Pattern.quote("\\end\\{proof\\}"));

结果将是&#34; Hello,World!&#34;。 See IDEONE demo

您拥有的字符串实际上是\begin\{theorem\} Hello, World! \end\{theorem\}。 Java字符串中的字面反斜杠加倍,当您需要将Java中的文字反斜杠与正则表达式匹配时,需要使用\\\\。为了避免使用backslash hellPattern.quote可以提供帮助,告诉正则表达式将其中的所有子模式视为文字。

有关Pattern.quote的更多详细信息,请参阅documentation

  

返回指定String的文字模式String   此方法生成String,可用于创建与Pattern字符串匹配的s,就好像它是文字模式一样。

     

输入序列中的元字符或转义序列没有特殊含义。

答案 1 :(得分:0)

你的第一个正则表达式必须是:

Pattern THEOREM_REGEX = Pattern.compile("\\\\begin\\\\\\{theorem\\\\\\}(.+?)\\\\end\\\\\\{theorem\\\\\\}");

因为您正在尝试匹配正则表达式中需要 \\\\ 的反斜杠。

答案 2 :(得分:0)

您的测试代码中似乎存在其他答案无法解决的错误。您可以像这样创建测试字符串:

String source = "\\begin\\{theorem\\} Hello, World! \\end\\{theorem\\}";

...但是在文中你说源字符串应该是:

\begin{theorem} Hello, World! \end{theorem}

如果这是真的,字符串文字应为:

"\\begin{theorem} Hello, World! \\end{theorem}"

要创建正则表达式,您可以使用:

Pattern.quote("\\begin{theorem}") + "(.*?)" + Pattern.quote("\\end{theorem}")

...或手动转义:

"\\\\begin\\{theorem\\}(.*?)\\\end\\{theorem\\}"