假设要搜索的文字是pqr
。
"http://abc.zzz/pqr/xyz" -> Should not match
"/pqr/" -> Should Match
"pqr" -> Should Match
"http://abc.zzz/pqr/pqr/" -> Should not match
"http://abc.zzz/pqr/pqr/ pqr" -> Should match the last "pqr"
"www.pqr.zzz" -> Should not match
我尝试使用以下正则表达式
((?:(?:(?:https?|ftp|file|mailto):)|www)[^ ]+?)?(pqr)
然后我找了group 1
,如果它是空的那么我认为它是一个匹配。但是http://abc.zzz/pqr/pqr/
这里有任何帮助来检测匹配的文本是否不是网址的一部分?
我认为最糟糕的情况是首先检测所有网址,然后存储匹配网址的开始和结束索引。然后尝试匹配pqr
并排除所有属于网址的人。我在想是否可以做得更好。
答案 0 :(得分:2)
考虑到您使用的是Java,您可以利用Java正则表达式引擎支持的约束宽度lookbehind 。这意味着您可以在模式中使用{n,m}
限制量词。现在,Java 8 supports even *
and +
quantifiers inside a lookbehind(虽然是非正式的),但这是一个错误,可能会在下一个版本中修复。因此,您可以使用某个范围,例如0 to 1000
(因为链接不太可能包含超过1K的符号,但您可以根据实际情况进行调整):
(?<!(?:(?:https?|ftp|file)://|mailto:)(?:www\.)?\S{0,1000})(?<!\bwww\.\S{0,1000})pqr
请参阅regex demo
第一个lookbehind (?<!(?:(?:https?|ftp|file)://|mailto:)(?:www\.)?\S{0,1000})
将检查pqr
前面是否没有完整的网址,(?<!\bwww\.\S{0,1000})
lookbehind将检查pqr
是否前面没有{{ 1}}。