我用谷歌搜索了regexinfo.com并且已经实现了几个小时,并且在我的生活中无法弄清楚这两个应该与meta标签匹配的正则表达式有什么问题。 任何帮助是极大的赞赏。 :)
Purp 1: 在preg_replace中使用$ 1时,捕获行的末尾的“>
'/<meta[\s]+[^>]*?name[\s]?=[\s"\']+keywords[\s"\']+content[\s]?=[\s"\']+([^"\']*)/ixU'
Purp 2: 不会随意捕捉线条,或多或少。 (别介意缺乏对''的支持)
'/<meta(?=[^>]*name="keywords")\s[^>$]*content="([^"]*)[">]*$/ixU
答案 0 :(得分:0)
我发现你使用了三个PCRE modifiersDocs:
i
(PCRE_CASELESS) - 看起来不错,因为标签和属性名称在HTML中不区分大小写。x
(PCRE_EXTENDED) - 您的模式看起来不需要这样。U
(PCRE_UNGREEDY) - 不确定你是否真的需要它,可能更容易使用默认值并控制它自己的每次重复,例如仅在需要时使用特定量词来更改默认值。您可能缺少的是m
(PCRE_MULTILINE)修饰符,使$
实际上与行尾相匹配。除非使用,$
匹配主题字符串的结尾。
一个解释正则表达式的好网站是http://www.regular-expressions.info/,如果我需要快速查找内容,我有时会查看,因为另一个good reference for PCRE都在一个文本文件中。
对于您的情况,可能此页面对what is greedy and how to deal with it感兴趣。
答案 1 :(得分:0)
省略可选的空格并假设属性值周围只有双引号,你的第一个正则表达式就等于:
'/<meta\s+name="keywords"\s+content="([^"]*?)/i'
如果属性恰好按该顺序列出,则应该匹配content
属性的开头引用之前的所有内容。在捕获组内部,[^"]*
应该使用属性值,但由于您使用了U
(ungreedy)标记,因此它最初不会消耗任何内容,就像[^"]*?
一样。这就是正则表达式的结束,所以它报告了一个成功的匹配。
换句话说,你当前的问题是你遗漏了收盘价。如果您想匹配整个代码,则还需要添加结束>
:
'/<meta\s+name="keywords"\s+content="([^"]*)">/i'
但正如我所说,只有在只有两个属性的情况下它们才有效,并且它们按照该顺序列出,并且它不考虑单引号或不引用的属性值或可选的空格。
您的第二个正则表达式通过使用前瞻匹配name
属性来处理排序问题。但它假设标签后面紧跟一个换行符,这不是你可以指望的东西。您应该使用结束>
来标记匹配结束:
'/<meta\s+(?=[^>]*name="keywords")[^>]*content="([^"]*)"[^>]*>/i'
如果你想允许可选的空格:
'/<meta\s+(?=[^>]*name\s*=\s*"keywords")[^>]*content\s*=\s*"([^"]*)"[^>]*>/i'
我要强调的是,你的问题不过度贪婪。这个正则表达式在没有U
标志的情况下工作,除了正常的,贪婪的量词之外什么都没有。
答案 2 :(得分:0)
这个经过测试的功能应该做得很好:
// Fetch keywords from META element.
function getKeywords($text) {
$re = '/# Match META tag having name=keywords values.
<meta # Start of META tag.
[^>]*? # Lazily match up to NAME attrib.
\bname\s*=\s* # NAME attribute name.
["\']?keywords[\'"]? # NAME attribute value.
[^>]*? # Lazily match up to CONTENT attrib.
\bcontent\s*=\s* # CONTENT attribute name.
(?| # Branch reset group for keywords value.
"([^"]*)" # Either $1.1: a double quoted,
| \'([^\']*)\' # or $1.2: single quoted value
) # End branch reset group.
[^>]* # Greedily match up to end of tag.
> # Literal end of META tag.
/ix';
if (preg_match($re, $text, $matches)) {
return $matches[1];
} else {
return 'No META tag with keywords.';
}
}
请注意,延迟修饰符不是必需的,但会使它更快地匹配。
附加2011-12-28 OP澄清了表明只有一行文字可用的问题,因此可能会截断META标记的CONTENT属性值。这是一个不同的正则表达式,它捕获到捕获组1的CONTENT属性值(可能被截断)和标记的其余部分(如果它全部在一行上):
// Fetch keywords CONTENT attrib value from META element.
function getKeywords($text) {
$re = '/# Match META tag having name=keywords values.
<meta # Start of META tag.
[^>]*? # Lazily match up to NAME attrib.
\bname\s*=\s* # NAME attribute name.
["\']?keywords[\'"]? # NAME attribute value.
[^>]*? # Lazily match up to CONTENT attrib.
\bcontent\s*=\s* # CONTENT attribute name.
(?| # Branch reset group for keywords value.
"([^"\r\n]*)"? # Either $1.1: a double quoted,
| \'([^\'\r\n]*)\'? # or $1.2: single quoted value
) # End branch reset group.
(?: # Grab remainder of tag (optional).
[^>\r\n]* # Greedily match up to end of tag.
> # Literal end of META tag.
)? # Grab remainder of tag (optional).
/ix';
if (preg_match($re, $text, $matches)) {
return $matches[1];
} else {
return 'No META tag with keywords.';
}
}