所以我有这个正则表达式(来自https://github.com/savetheinternet/Tinyboard/blob/master/inc/functions.php#L1620)
((?:https?:\/\/|ftp:\/\/|irc:\/\/)[^\s<>()"]+?(?:\([^\s<>()"]*?\)[^\s<>()"]*?)*)((?:\s|<|>|"|\.|\]|!|\?|,|,|")*(?:[\s<>()"]|$))
它适用于匹配链接,例如:http://stackoverflow.com/
等。
问题是,如何排除这些标记匹配(主要是url ja img部分):
[url]http://stackoverflow.com/[/url]
[url=http://stackoverflow.com/]http://stackoverflow.com/[/url]
[img]http://cdn.sstatic.net/stackoverflow/img/sprites.png[/img]
[img=http://cdn.sstatic.net/stackoverflow/img/sprites.png]
答案 0 :(得分:3)
要排除这个,您可以在表达式的开头添加此子模式:
(?:\[(url|img)](?>[^[]++|[(?!\/\g{-1}))*+\[\/\g{-1}]|\[(?:url|img)=[^]]*+])(*SKIP)(*FAIL)|your pattern here
这样做的目的是尝试匹配之前不需要的部分,并使用回溯控制动词(*FAIL)
强制正则表达式引擎失败。 (*SKIP)
动词强制正则表达式引擎在子模式失败之前不重试匹配的子字符串。
您可以找到有关这些功能的更多信息here。
注意:假设您使用PHP进行此模式,您可以通过将/
替换为默认分隔符~
来改善这一非常长的模式,以避免全部/
在模式中并使用具有Nowdoc语法的详细模式(x修饰符)。像这样你可以评论它,使它更具可读性并轻松改进模式
示例:
$pattern = <<<'EOF'
~
### skipping url and img bbcodes ###
(?:
\[(url|img)] # opening bbcode tag
(?>[^[]++|[(?!/\g{-1}))*+ # possible content between tags
\[/\g{-1}] # closing bbcode tag
|
\[(?:url|img)= [^]]*+ ] # self closing bbcode tags
)(*SKIP)(*FAIL) # forces to fail and skip
| # OR
### a link ###
(
(?:https?|ftp|irc):// # protocol
[^\s<>()"]+?
(?:
\( [^\s<>()"]*? \) # part between parenthesis
[^\s<>()"]*?
)*
)
(
(?:[]\s<>".!?,]|,|")*
(?:[\s<>()"]|$)
)
~x
EOF;
答案 1 :(得分:0)
您可以使用负面后瞻断言解决此问题。
(?<!pattern)
在您的情况下,您可以检查匹配链接之前是否没有]
或=
字符。
正则表达式将确保确实没有发生这种情况:
(?<!(?:\=|\]))((?:https?:\/\/|ftp:\/\/|irc:\/\/)[^\s<>()"]+?(?:\([^\s<>()"]*?\)[^\s<>()"]*?)*)((?:\s|<|>|"|\.|\]|!|\?|,|,|")*(?:[\s<>()"]|$))
请注意,在开头添加的唯一部分是(?<!(?:\=|\]))
,并且它与<a href=http://example.com>
之类的链接不匹配,但您的问题没有指定此...所以如果提出问题这种预期的行为或使用负面看法自己解决。