带有php preg_replace和不够贪婪的表达式的过度贪婪的regexp backreference
我已经在谷歌搜索regexinfo.com并进行了数小时的实验,但我一辈子都无法找出这两个应该匹配元标记的正则表达式有什么问题。 非常感谢您的帮助。:) 目的1: 在preg_replace中使用$1时,捕获行末“>的内容带有php preg_replace和不够贪婪的表达式的过度贪婪的regexp backreference,php,regex,Php,Regex,我已经在谷歌搜索regexinfo.com并进行了数小时的实验,但我一辈子都无法找出这两个应该匹配元标记的正则表达式有什么问题。 非常感谢您的帮助。:) 目的1: 在preg_replace中使用$1时,捕获行末“>的内容 '/<meta[\s]+[^>]*?name[\s]?=[\s"\']+keywords[\s"\']+content[\s]?=[\s"\']+([^"\']*)/ixU' '/]*?名称[\s]?=[\s”\']+关键字[\s”\']+内容[\s]?=[\s
'/<meta[\s]+[^>]*?name[\s]?=[\s"\']+keywords[\s"\']+content[\s]?=[\s"\']+([^"\']*)/ixU'
'/]*?名称[\s]?=[\s”\']+关键字[\s”\']+内容[\s]?=[\s”\']+([^“\']*)/ixU'
目的2:
不捕捉线条,或多或少是一时兴起。(更不用说缺少对')
'/]*name=“keywords”)\s[^>$]*content=“([^”]*)[“>]*$/ixU
我发现您正在使用三个:
i
(PCRE\u无大小写)-看起来不错,因为标记和属性名称在HTML中不区分大小写x
(PCRE\U扩展)-您的图案不需要像它看起来那样使用它U
(PCRE_UNGREEDY)-不确定您是否真的需要这个,使用默认值并自己控制每个重复可能更容易,例如,仅在需要时使用特定的量词更改默认值m
(PCRE\u MULTILINE)修饰符,该修饰符使$
与行尾实际匹配。除非使用,$
匹配主题字符串的结尾
解释正则表达式的一个好网站是,如果我需要快速查找内容,我有时会在那里查找,因为另一个都在一个文本文件中
对于您的情况,此页面可能很有趣。省去可选的空白,并假设属性值周围只有双引号,您的第一个正则表达式相当于:
'/<meta\s+name="keywords"\s+content="([^"]*?)/i'
但正如我所说的,只有当只有两个属性并且它们是按顺序列出的时候,这才有效,并且它不考虑单引号或无引号的属性值,或者可选的空白
第二个正则表达式通过对name
属性进行前瞻性匹配来处理排序问题。但它假定标记后面紧接着一个换行符,这是您无法指望的。您应该使用结束符
标记比赛结束:
'/<meta\s+(?=[^>]*name="keywords")[^>]*content="([^"]*)"[^>]*>/i'
'/]*name=“keywords”)[^>]*content=“([^”]*)”[^>]*>/i'
如果您想允许可选的空白:
'/<meta\s+(?=[^>]*name\s*=\s*"keywords")[^>]*content\s*=\s*"([^"]*)"[^>]*>/i'
'/]*name\s*=\s*“关键字”)[^>]*content\s*=\s*”([^“]*)“[^>]*>/i”
我想强调的是,你的问题不是过分贪婪。这个正则表达式在没有
U
标志的情况下工作,除了正常的贪婪量词外,没有其他任何东西。这个经过测试的函数应该做得很好:
//从元元素获取关键字。
函数getKeywords($text){
$re='/#匹配具有name=关键字值的元标记。
]*?#懒洋洋地匹配名称attrib。
\bname\s*=\s*#NAME属性名称。
[“\”]?关键字[\”]?\35;名称属性值。
[^>]*?#懒洋洋地匹配内容属性。
\b内容\s*=\s*#内容属性名称。
(?|#为关键字值分支重置组。
“([^”]*)”#1.1美元:双引号,
|\'([^\']*)\'\或$1.2:单引号
)#端分支重置组。
[^>]*#贪婪地匹配到标签的末尾。
>#元标记的文字结尾。
/九",;
if(preg_匹配($re,$text,$matches)){
返回$matches[1];
}否则{
返回“没有带关键字的元标记”;
}
}
请注意,惰性修饰符不是必需的,但会使其匹配速度加快一点点
附加2011-12-28OP澄清了一个问题,表明只有一行文本可用,因此元标记的内容属性值可能会被截断。下面是一个不同的正则表达式,它将内容属性值捕获到捕获组1中(可能会被截断)以及标记的其余部分(如果全部在一行):
//从元元素获取关键字内容属性值。
函数getKeywords($text){
$re='/#匹配具有name=关键字值的元标记。
]*?#懒洋洋地匹配名称attrib。
\bname\s*=\s*#NAME属性名称。
[“\”]?关键字[\”]?\35;名称属性值。
[^>]*?#懒洋洋地匹配内容属性。
\b内容\s*=\s*#内容属性名称。
(?|#为关键字值分支重置组。
“([^”\r\n]*)”?#1.1美元:双引号,
|\'([^\'\r\n]*)\'?#或$1.2:单引号
)#端分支重置组。
(?:#抓取标签的剩余部分(可选)。
[^>\r\n]*#贪婪地匹配到标记的末尾。
>#元标记的文字结尾。
)?抓住标签的剩余部分(可选)。
/九",;
if(preg_匹配($re,$text,$matches)){
返回$matches[1];
}否则{
返回“没有带关键字的元标记”;
}
}
请添加要匹配的主题字符串。它还应该有助于向您展示,使用HTML解析器来实现正则表达式更容易。+1@hakre-这不会是一个HTML/regex问题,因此如果有人没有链接到,那么我想这次我会受到打击:-Dlol,同意,这是一个痛苦的问题。尽管如此,我还是想让***工作起来。如果我永远被卡住,我可能会让get_meta_数据旋转一圈。永远不要使用'U'
修饰符!它从来都不需要,它唯一的目的就是混淆。相反,只需向需要它的量词添加一个?
ungreedy修饰符。(而且这个问题也不需要任何惰性量词。)使用“/时,您仍然省略了结束引号。上面的第一个正则表达式只是您自己的正则表达式的简化版本,包括t
'/<meta\s+(?=[^>]*name="keywords")[^>]*content="([^"]*)"[^>]*>/i'
'/<meta\s+(?=[^>]*name\s*=\s*"keywords")[^>]*content\s*=\s*"([^"]*)"[^>]*>/i'