我在PHP中有两个字符串:
$string = '<a href="http://localhost/image1.jpeg" /></a>';
和
$string2 = '[caption id="attachment_5" align="alignnone" width="483"]<a href="http://localhost/image1.jpeg" /></a>[/caption]';
我正在尝试匹配第一种类型的字符串。那是没有被'[caption ...]'和'[/ caption]'包围的字符串。到目前为止,我想使用这样的东西:
$pattern = '/(?<!\[caption.*\])(?!\[\/caption\])(<a.*><img.*><\/a>)/';
但PHP也匹配第一个字符串以及此模式,即使它不是'[caption'和零个或多个字符后跟']'。是什么赋予了?为什么这是正确的模式?
感谢。
答案 0 :(得分:0)
PHP不支持可变长度后视,因此模式的这部分无效:
(?<!\[caption.*\])
应该警告你这件事。
此外,.*
始终匹配可能的金额。因此,您的模式可能会导致匹配多个标记重叠。相反,请使用[^>]
(匹配任何不是右括号的内容),因为右括号不应出现在img
标记内。
要解决后视问题,为什么不直接检查结束标记?这应该足够了(假设标题标签仅以与您所示的方式类似的方式使用)。
$pattern = '|(<a[^>]*><img[^>]*></a>)(?!\[/caption\])|';
匹配包含/
的模式时,请使用另一个字符作为模式分隔符,以避免倾斜牙签综合征。您可以在模式周围使用几乎任何非字母数字字符。
更新:以前的正则表达式基于您提供的示例正则表达式,而不是示例数据。如果要匹配不包含图像的链接,请执行以下操作:
$pattern = '|(<a[^>]*>[^<]*</a>)(?!\[/caption\])|';
请注意,这不允许链接中间的任何标记。如果您允许标记(例如使用.*?
),则正则表达式可以匹配从[caption]
开始到其他地方结束的内容。
答案 1 :(得分:0)
我不知道你的正则表达式如何匹配任何一个字符串,因为你正在寻找<a.*><img.*><\/a>
,而且两个锚点都不包含<img...
标记。此外,寻找和禁止caption
位的两个子表达式看起来很奇怪。最后,您需要确保您的代码匹配位不会贪婪,即不要使用.*
但[^>]*
。
你的意思是这样吗?
$pattern = '/(<a[^>]*>(<img[^>]*>)?<\/a>)(?!\[\/caption\])/'
在regex101上进行测试。
修改:根据dan1111的建议和更新的regex101链接删除了无用的前瞻。
答案 2 :(得分:-1)
Lookbehind不允许非固定长度模式,即(*,+,?),我认为这个/<a.*><\/a>(?!\[\/caption\])/
足以满足您的要求