0

我有一个正则表达式试图检测标题和链接标记:

[title](http://link.com)

到目前为止,我有:

(\[)(.*?)(\])(\(((http[s]?)|ftp):\/\/)(.*?)(\))

当无标题链接标记在它之前时,它会检测到很多

[http://google.com] [Digg](http://digg.com)
[Internal Page] Random other text [Digg](http://digg.com)

如何将正则表达式限制为标题链接?

有标题和无标题链接的完整 PHP:

    // Titled Links
    // [Digg](http://digg.com)
    // [Google](http://google.com)
    $text = preg_replace_callback(
        '/(\[)(.*?)(\])(\(((http[s]?)|ftp):\/\/)(.*?)(\))/',
        function ($match) {
            $link = trim($match[7]);
            $ret = "<a target='_blank' href='" . strtolower($match[5]) . "://" . $link . "'>" . trim($match[2]) . "</a>";
            if (strtolower($match[5]) == "http") {
                $ret .= "<img src='/images/link_http.png' class='link' />";
            } else if (strtolower($match[5]) == "https") {
                $ret .= "<img src='/images/link_https.png' class='link' />";
            } else if (strtolower($match[5]) == "ftp") {
                $ret .= "<img src='/images/link_ftp.png' class='link' />";
            }
            return $ret;
        },
        $text
    );

    // Untitled Links
    // [Internal Page]
    // [http://google.com]
    $text = preg_replace_callback(
        '/(\[)(.*?)(\])/',
        function ($match) {
            $link = trim($match[2]);

            $ret = "";
            if ($this->startsWith(strtolower($link), "https")) {
                $ret = "<a target='_blank' href='" . $link . "'>" . $link . "</a>";
                $ret .= "<img src='/images/link_https.png' class='link' />";
            } else if ($this->startsWith(strtolower($link), "http")) {
                $ret = "<a target='_blank' href='" . $link . "'>" . $link . "</a>";
                $ret .= "<img src='/images/link_http.png' class='link' />";
            } else if ($this->startsWith(strtolower($link),  "ftp")) {
                $ret = "<a target='_blank' href='" . $link . "'>" . $link . "</a>";
                $ret .= "<img src='/images/link_ftp.png' class='link' />";
            } else {
                $link = str_replace(" ", "_", $link);
                $ret = "<a href='" . $link . "'>" . trim($match[2]) . "</a>";
            }
            return $ret;
        },
        $text
    );
4

4 回答 4

2

如果您尝试通过 Markdown 链接,您可能希望直接从源代码获取正则表达式和逻辑:

https://github.com/michelf/php-markdown/blob/lib/Michelf/Markdown.php#L510

https://github.com/tanakahisateru/js-markdown-extra/blob/master/js-markdown-extra.js#L630

于 2013-05-18T18:00:30.287 回答
0

而不是(.*?)尝试匹配您真正不想要的东西,例如空格,例如([^\s]+).

此外,整个第二部分是可选的(如果你可以有一个无标题的链接),所以添加?@Arnout 建议的,例如

(\(((http[s]?)|ftp):\/\/)([^\s]+)(\))?

我还可以建议,(尽管我不确定它似乎在 PHP regex 中是否受支持,但使用空格标志并将其分成几行以提高可读性:

/
  (
    \[
  )
  (.*?)
  (
    \]
  )
  (
    \(
     (
       (http[s]?)
         |
       ftp
     )
     :\/\/
  )
  (.*?)
  (
    \)
  )
/x

这更清晰,也更容易看到:

  • 可能[s]?只是s?
  • 方案括号应该是 ((?:https?)|(?:ftp)) 或者它只是 ORs 上的f,你会得到额外的不需要的捕获。

您也可以在正则表达式中对其进行评论(同样,我不确定您是否可以使用 PHP)。

于 2013-05-18T17:55:35.303 回答
0

这有效,但没有您要匹配的所有组的括号。

\[[\w\s]+\]\((https?|ftp)://[^)]+\)
于 2013-05-18T18:08:11.993 回答
0

通过附加“?”使标题成为可选的 到与标题匹配的组。

于 2013-05-18T17:33:59.930 回答