Php preg_match:通过匹配其中的一个单词来返回整个url

Php preg_match:通过匹配其中的一个单词来返回整个url,php,regex,preg-match,Php,Regex,Preg Match,如果我有包含以下内容的文本: 测试 如何通过匹配具有“abc=xxxx”的单词来预匹配,因此我得到: www.example.com/test?abc=xxxx&def=yyyy&ghi=zzzzz 当您在此处搜索URL时,有必要弄清楚它与上下文的区别 URL通常不包含空格,并且通常包含在某种引号或括号中,以便于识别: URL——被空格包围-- “URL”--在您的示例中引用-- --标记URL的类方法-- 这将允许将URL描述为以下表达式 ~(?P[^\s“\']+)~ 在您的示例中,仅

如果我有包含以下内容的文本:

测试
如何通过匹配具有“abc=xxxx”的单词来预匹配,因此我得到:

www.example.com/test?abc=xxxx&def=yyyy&ghi=zzzzz

当您在此处搜索URL时,有必要弄清楚它与上下文的区别

URL通常不包含空格,并且通常包含在某种引号或括号中,以便于识别:

URL——被空格包围--
“URL”--在您的示例中引用--
--标记URL的类方法--
这将允许将URL描述为以下表达式

~(?P[^\s“\']+)~
在您的示例中,仅在文档上运行此操作已经在这里做了一些工作,它给出了13个结果,其中12个是误报,但URL位于:

#1 h1、#2测试、#3/h1、,
#4部分,5个html,6个元素,
#7 a,#8 href=,
#9 www.example.com/test?abc=xxxx&def=yyyy&ghi=zzzzz,
#10/a、#11更多、#12 html、,
#13个要素。
幸运的是,在您的案例中,URL是什么,您有更多的条件,因此可以添加这些条件。例如,必须有一个查询字符串。它必须包含一个问号:

~(?P[^\s“\'?]+\?[^\s“\'?]+)~

问号已被排除在允许的字符组之外,该组已被分割为两个,并且在中间需要问号。因为URL只能包含一次,所以这是完全好的。

现在只剩下一场比赛了

www.example.com/test?abc=xxxx&def=yyyy&ghi=zzzzz
因为这现在真的很难读,让我们把它写下来:

~
    (?(DEFINE)
        (?<Chars> [^\s<>"\'?]+)
    )

    (?P<url> (?&Chars) \? (?&Chars) )
~x
因此,只要您对特定URL感兴趣,使用正则表达式执行此操作就相对简单,但是:文档中的URL不能被规范化,其他类似问题也可能会被规范化。因此,通常最值得先规范化URL,然后再继续进行。例如,在查询信息部分中查找URL参数时

在编写本文时,我实际上认为,对从文档中获取的URL的过滤应该独立于解析方法。正如其他用户所评论的,您可能希望使用HTML解析器而不是正则表达式。或者您可能希望两者都使用

让我们首先考虑正则表达式场景。下面是一个具有正确URL解析的正则表达式变体。作为预防措施,URL的最大长度限制在6到256字节之间:

$matcher  = new PregStringMatcher('~([^\s<>"\']{6,256})~');
$segments = new StringMatcherIterator($matcher, $input);
$all      = new DecoratingIterator($segments, 'Net_URL2');
$urls     = new CallbackFilterIterator($all, function (Net_URL2 $url) {
    return isset($url->getQueryVariables()['abc']);
});

foreach ($urls as $url) {
    echo $url->getQueryVariables()['abc'], ' - ', $url, "\n";
}

如果你现在考虑切换到HTML解析器,你就不需要改变太多的代码。因为过滤逻辑保持不变,你只需要交换下面的<强>可遍历< /强>:

$doc   = new DOMDocument();
$saved = libxml_use_internal_errors(true);
$doc->loadHTML($input);
libxml_use_internal_errors($saved);

$attributes = (new DOMXPath($doc))->query('//@href');
$segments   = new DecoratingIterator($attributes, function (DOMAttr $attr) {
    return $attr->nodeValue;
});
代码的其余部分可以保持不变,本例中的结果是相同的。因此,我希望这些示例非常有用,并展示了如何处理regex模式以及如何添加更多检查的一些方法

下面是带有正则表达式和HTML解析器的完整代码示例。URL筛选器在这两个方面都是相同的:

<?php
/**
 * preg_match: return entire url by matching a word inside it
 *
 * @link http://stackoverflow.com/a/29481904/367456
 */

require __DIR__ . '/vendor/autoload.php';

$input = <<<BUFFER
<h1> Test </h1>
<some html elements>
<a href="www.example.com/test?%61%62%63=xxxx&def=yyyy&ghi=zzzzz"></a>

<more html elements>
BUFFER;

// Regex based retrieval

$matcher  = new PregStringMatcher('~([^\s<>"\']{6,256})~');
$segments = new StringMatcherIterator($matcher, $input);
$all  = new DecoratingIterator($segments, 'Net_URL2');
$urls = new CallbackFilterIterator($all, function (Net_URL2 $url) {
    return isset($url->getQueryVariables()['abc']);
});

foreach ($urls as $url) {
    echo $url->getQueryVariables()['abc'], ' - ', $url, "\n";
}

// DOMDocument based retrieval

$doc   = new DOMDocument();
$saved = libxml_use_internal_errors(true);
$doc->loadHTML($input);
libxml_use_internal_errors($saved);

$attributes = (new DOMXPath($doc))->query('//@href');
$segments   = new DecoratingIterator($attributes, function (DOMAttr $attr) {
    return $attr->nodeValue;
});
$all  = new DecoratingIterator($segments, 'Net_URL2');
$urls = new CallbackFilterIterator($all, function (Net_URL2 $url) {
    return isset($url->getQueryVariables()['abc']);
});

foreach ($urls as $url) {
    echo $url->getQueryVariables()['abc'], ' - ', $url, "\n";
}

您尝试过什么吗?^在问题中添加您的尝试您应该解析url和查询字符串,而不是使用正则表达式。如果该文本是html,则使用DOM和一些xpath。
//a[contains(@href,'abc=')]
?我很高兴看到评论。好吧。要学习DOM+xpath吗
$doc   = new DOMDocument();
$saved = libxml_use_internal_errors(true);
$doc->loadHTML($input);
libxml_use_internal_errors($saved);

$attributes = (new DOMXPath($doc))->query('//@href');
$segments   = new DecoratingIterator($attributes, function (DOMAttr $attr) {
    return $attr->nodeValue;
});
<?php
/**
 * preg_match: return entire url by matching a word inside it
 *
 * @link http://stackoverflow.com/a/29481904/367456
 */

require __DIR__ . '/vendor/autoload.php';

$input = <<<BUFFER
<h1> Test </h1>
<some html elements>
<a href="www.example.com/test?%61%62%63=xxxx&def=yyyy&ghi=zzzzz"></a>

<more html elements>
BUFFER;

// Regex based retrieval

$matcher  = new PregStringMatcher('~([^\s<>"\']{6,256})~');
$segments = new StringMatcherIterator($matcher, $input);
$all  = new DecoratingIterator($segments, 'Net_URL2');
$urls = new CallbackFilterIterator($all, function (Net_URL2 $url) {
    return isset($url->getQueryVariables()['abc']);
});

foreach ($urls as $url) {
    echo $url->getQueryVariables()['abc'], ' - ', $url, "\n";
}

// DOMDocument based retrieval

$doc   = new DOMDocument();
$saved = libxml_use_internal_errors(true);
$doc->loadHTML($input);
libxml_use_internal_errors($saved);

$attributes = (new DOMXPath($doc))->query('//@href');
$segments   = new DecoratingIterator($attributes, function (DOMAttr $attr) {
    return $attr->nodeValue;
});
$all  = new DecoratingIterator($segments, 'Net_URL2');
$urls = new CallbackFilterIterator($all, function (Net_URL2 $url) {
    return isset($url->getQueryVariables()['abc']);
});

foreach ($urls as $url) {
    echo $url->getQueryVariables()['abc'], ' - ', $url, "\n";
}