找到匹配时获取数组的其他部分
Get other part of array when match found
这是我正在使用的正则表达式。它工作正常,但现在我正在尝试获取结果。
基本上,如果 name/property/etc 包含 "title",我希望它回应标题元标记的内容。
也就是说,我要的是对应的out[2],而不是out[1],当out[1]中包含"title"(不区分大小写)。
$pattern = '
~<\s*meta\s
# using lookahead to capture type to
(?=[^>]*?
\b(?:name|property|http-equiv)\s*=\s*
(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|
([^"\'>]*?)(?=\s*/?\s*>|\s\w+\s*=))
)
# capture content to
[^>]*?\bcontent\s*=\s*
(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|
([^"\'>]*?)(?=\s*/?\s*>|\s\w+\s*=))
[^>]*>
~ix';
if(preg_match_all($pattern, $link_html, $out))
{
foreach ($out[1] as $out)
{
echo $out.'<br>';
}
}
这应该可以通过在 foreach
循环中捕获数组索引来实现,如下所示:
foreach ($out[1] as $index => $out) {
if(stristr($out, 'title')) echo $out[2][$index].'<br>';
}
您要求使用正则表达式,但使用 HTML 解析器和 XPath 会更容易且更易读:
<?php
$html = <<< HTML
<html>
<head>
<meta name="author" lang="en" content="Gordon" />
<meta name="title" lang="en" content="match this" />
<meta property="title" lang="en" content="and this" />
<meta http-equiv="title" lang="en" content="and also this" />
<meta foo="title" content="but not this" />
</head>
<body>Use DOMDocument for HTML parsing instead</body>
</html>
HTML;
libxml_use_internal_errors(true);
$dom = new DOMDocument;
$dom->loadHTML($html);
libxml_use_internal_errors(false);
$xpath = new DOMXPath($dom);
$nodes = $xpath->evaluate(
'//meta[
@*[
contains("name|property|http-equiv", name())
and contains(., "title")
]
]/@content'
);
foreach ($nodes as $node) {
echo $node->nodeValue, PHP_EOL;
}
输出:
match this
and this
and also this
XPath 意味着 查找任何元标记的所有内容属性,其中任何属性名称是字符串 "name|property|http-equiv" 的一部分并且包含值 "title" 在该属性中。
正如您希望看到的那样,XPath 本身读起来几乎就像是自然语言(与您使用的正则表达式相反)。
这是我正在使用的正则表达式。它工作正常,但现在我正在尝试获取结果。
基本上,如果 name/property/etc 包含 "title",我希望它回应标题元标记的内容。
也就是说,我要的是对应的out[2],而不是out[1],当out[1]中包含"title"(不区分大小写)。
$pattern = '
~<\s*meta\s
# using lookahead to capture type to
(?=[^>]*?
\b(?:name|property|http-equiv)\s*=\s*
(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|
([^"\'>]*?)(?=\s*/?\s*>|\s\w+\s*=))
)
# capture content to
[^>]*?\bcontent\s*=\s*
(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|
([^"\'>]*?)(?=\s*/?\s*>|\s\w+\s*=))
[^>]*>
~ix';
if(preg_match_all($pattern, $link_html, $out))
{
foreach ($out[1] as $out)
{
echo $out.'<br>';
}
}
这应该可以通过在 foreach
循环中捕获数组索引来实现,如下所示:
foreach ($out[1] as $index => $out) {
if(stristr($out, 'title')) echo $out[2][$index].'<br>';
}
您要求使用正则表达式,但使用 HTML 解析器和 XPath 会更容易且更易读:
<?php
$html = <<< HTML
<html>
<head>
<meta name="author" lang="en" content="Gordon" />
<meta name="title" lang="en" content="match this" />
<meta property="title" lang="en" content="and this" />
<meta http-equiv="title" lang="en" content="and also this" />
<meta foo="title" content="but not this" />
</head>
<body>Use DOMDocument for HTML parsing instead</body>
</html>
HTML;
libxml_use_internal_errors(true);
$dom = new DOMDocument;
$dom->loadHTML($html);
libxml_use_internal_errors(false);
$xpath = new DOMXPath($dom);
$nodes = $xpath->evaluate(
'//meta[
@*[
contains("name|property|http-equiv", name())
and contains(., "title")
]
]/@content'
);
foreach ($nodes as $node) {
echo $node->nodeValue, PHP_EOL;
}
输出:
match this
and this
and also this
XPath 意味着 查找任何元标记的所有内容属性,其中任何属性名称是字符串 "name|property|http-equiv" 的一部分并且包含值 "title" 在该属性中。
正如您希望看到的那样,XPath 本身读起来几乎就像是自然语言(与您使用的正则表达式相反)。