【问题标题】:Why matcher.find() for input parameter always return 'false'?为什么输入参数的 matcher.find() 总是返回'false'?
【发布时间】:2020-03-11 18:37:41
【问题描述】:

我有一个奇怪的情况,我觉得正则表达式匹配器很难理解。

当我将下一个输入参数 issueBody 传递给匹配器时,matcher.find() 总是返回 false,同时传递与 issueBody - 它按预期工作。

正则表达式函数

private Map<String, String> extractCodeSnippet(Set<String> resolvedIssueCodeLines, String issueBody) {
        String codeSnippetForCodeLinePattern = "\\(Line #%s\\).*\\W\\`{3}\\W+(.*)(?=\\W+\\`{3})";
        Map<String, String> resolvedIssuesMap = new HashMap<>();

        for (String currentResolvedIssue : resolvedIssueCodeLines) {
            String currentCodeLinePattern = String.format(codeSnippetForCodeLinePattern, currentResolvedIssue);

            Pattern pattern = Pattern.compile(currentCodeLinePattern, Pattern.MULTILINE);
            Matcher matcher = pattern.matcher(issueBody);

            while (matcher.find()) {
                resolvedIssuesMap.put(currentResolvedIssue, matcher.group());
            }
        }
        return resolvedIssuesMap;
    }

以下总是返回 false

Pattern pattern = Pattern.compile(currentCodeLinePattern, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(issueBody);

虽然以下总是返回 true

Pattern pattern = Pattern.compile(currentCodeLinePattern, Pattern.MULTILINE);
Matcher matcher = pattern.matcher("**SQL_Injection** issue exists @ **VB_3845_112_lines/encode.frm** in branch **master**\n" +
                        "\n" +
                        "Severity: High\n" +
                        "\n" +
                        "CWE:89\n" +
                        "\n" +
                        "[Vulnerability details and guidance](https://cwe.mitre.org/data/definitions/89.html)\n" +
                        "\n" +
                        "[Internal Guidance](https://checkmarx.atlassian.net/wiki/spaces/AS/pages/79462432/Remediation+Guidance)\n" +
                        "\n" +
                        "[ppttx](http://WIN2K12-TEMP/bbcl/ViewerMain.aspx?planid=1010013&projectid=10005&pathid=1)\n" +
                        "\n" +
                        "Lines: 41 42 \n" +
                        "\n" +
                        "---\n" +
                        "[Code (Line #41):](null#L41)\n" +
                        "```\n" +
                        "    user_name = txtUserName.Text\n" +
                        "```\n" +
                        "---\n" +
                        "[Code (Line #42):](null#L42)\n" +
                        "```\n" +
                        "    password = txtPassword.Text\n" +
                        "```\n" +
                        "---\n");

我的问题是 - 为什么?这两种说法有什么区别?

【问题讨论】:

  • 您还可以显示分配 issueBody 字符串的位置/方式吗?也许有什么问题。
  • 我的第一个猜测是 issueBody 是使用错误字符集从字节流创建的。
  • @Andreas - 你是对的。它们是不相同的。为什么会这样?需要做什么?
  • 嗯,还有Pattern pattern = Pattern.compile(currentCodeLinePattern, Pattern.UNIX_LINES);?注意 Pattern.MULTILINE 不是必需的,因为您的模式既没有 ^ 也没有 $
  • @WiktorStribiżew - 成功了!我想我永远不会有Pattern.MULTILINE 是问题...谢谢!

标签: java regex matcher


【解决方案1】:

TL;DR:

通过使用Pattern.UNIX_LINES,您告诉Java 正则表达式引擎匹配. 除换行符以外的任何字符,LF。使用

Pattern pattern = Pattern.compile(currentCodeLinePattern, Pattern.UNIX_LINES);

在您的硬编码字符串中,您只有换行符,LF 结尾,而您的 issueBody 很可能包含 \r\n,CRLF 结尾。您的模式仅与 \W 匹配单个非单词字符(请参阅\\W\\`{3} 模式部分),但 CRLF 由两个非单词字符组成。默认情况下,. 不匹配换行符,因此它既不匹配 \r, CR 也不匹配 \n, LF。 \(Line #%s\).*\W\`{3} 正因为如此而失败:

  • \(Line #%s\) - 匹配 (Line #&lt;NUMBER&gt;)
  • .* - 匹配除任何换行符以外的 0 个或多个字符(最多 CR 或 CRLF)
  • \W - 匹配除字母/数字/_ 以外的字符(因此,仅匹配 \r\n
  • \`{3} - 3 个反引号 - 仅当有 \n 结尾而不是 \r\n (CRLF) 时才匹配。

同样,通过使用 Pattern.UNIX_LINES,您可以告诉 Java 正则表达式引擎与 . 匹配除换行符 LF 之外的任何字符。

顺便说一句,Pattern.MULTILINE 仅使 ^ 匹配每行的开头,而 $ 匹配每行的结尾,因为您的模式中既没有 ^ 也没有 $ ,您可以放心地放弃此选项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多