【问题标题】:Java regex to parse any number of Markdown-style links用于解析任意数量的 Markdown 样式链接的 Java 正则表达式
【发布时间】:2014-05-14 14:29:22
【问题描述】:

我正在尝试解析任何出现的降价样式链接的字符串,即[text](link)。我能够获取字符串中的第一个链接,但如果我有多个链接,我将无法访问其余链接。这是我试过的,你可以在ideone上运行它:

Pattern p;
try {
    p = Pattern.compile("[^\\[]*\\[(?<text>[^\\]]*)\\]\\((?<link>[^\\)]*)\\)(?:.*)");
} catch (PatternSyntaxException ex) {
    System.out.println(ex);
    throw(ex);
}
Matcher m1 = p.matcher("Hello");
Matcher m2 = p.matcher("Hello [world](ladies)");
Matcher m3 = p.matcher("Well, [this](that) has [two](too many) keys.");
System.out.println("m1 matches: " + m1.matches());  // false
System.out.println("m2 matches: " + m2.matches());  // true
System.out.println("m3 matches: " + m3.matches());  // true
System.out.println("m2 text: " + m2.group("text")); // world
System.out.println("m2 link: " + m2.group("link")); // ladies
System.out.println("m3 text: " + m3.group("text")); // this
System.out.println("m3 link: " + m3.group("link")); // that
System.out.println("m3 end: " + m3.end());          // 44 - I want 18
System.out.println("m3 count: " + m3.groupCount()); // 2 - I want 4
System.out.println("m3 find: " + m3.find());        // false - I want true

我知道我不能拥有repeating groups,但我认为find 会起作用,但它并没有像我预期的那样起作用。如何修改我的方法以便解析每个链接?

【问题讨论】:

    标签: java regex markdown


    【解决方案1】:

    你不能一个接一个地检查比赛,然后从上一场比赛之后的索引开始下一场比赛吗?你可以使用这个正则表达式:

    \[(?<text>[^\]]*)\]\((?<link>[^\)]*)\)
    

    Find() 方法尝试查找所有匹配项,即使匹配项是整个字符串的子字符串。每次调用 find 都会获得下一个匹配项。 Matches() 尝试匹配整个字符串,如果不匹配则失败。使用这样的东西:

    while (m.find()) {
        String s = m.group(1);
        // s now contains "BAR"
    }
    

    【讨论】:

    • 我尝试了类似的语法,但m3.matches()false,可能是因为尾随字符不是)。关于如何解决这个问题的任何建议?
    • 我猜您上述模式的问题是 (?:.*) 导致匹配一直持续到字符串的末尾。所以你在路上通过了所有其他潜在的比赛。我会使用我建议的模式并从字符串中获取所有匹配项。
    • 奇怪的是matches是假的。 Find 确实给出了答案中使用的模式的结果。在这里测试:java-regex-tester.appspot.com
    • .matches()false"\\[(?&lt;text&gt;[^\\]]*)\\]\\((?&lt;link&gt;[^\\)]*)\\)"。但是.find()true。我想我明白我必须做什么,但你能写下要做什么才能得到每对组,以便我接受你的回答吗?
    【解决方案2】:

    我用来匹配您需要的正则表达式(不带组)是\[\w+\]\(.+\)

    这只是为了向您展示它的简单性。基本上是这样:

    • 过滤一个正方形:\[
    • 后跟任何单词 char(至少 1 个):\w+
    • 然后广场:\]

    这将寻找这些模式[blabla]

    那么括号也一样...

    • 过滤括号:\(
    • 后跟任何字符(至少 1 个):.+
    • 然后是括号:\)

    所以它过滤(ble...ble...)

    现在,如果您想将匹配项存储在组中,您可以使用额外的括号,如下所示:

    (\[\w+\])(\(.+\)) 这样你就可以存储单词和链接了。

    希望能提供帮助。

    我在 regexplanet.com 上尝试过,它正在工作

    更新:解决方法.*(\[\w+\])(\(.+\))*.*

    【讨论】:

    • 这与我在 Farhad 的回答中遇到的问题相同。
    • 你可以试试这个解决方法吗,我已经在最后更新了帖子,因为这里不能发布它
    • 对,但我的问题是我只能找到第一个default和第一个key组。
    猜你喜欢
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多