如何获得两个子串之间的子串?

时间:2017-08-30 12:53:41

标签: php substring preg-match-all

我想在两个子串之间提取子串。问题是它只会提取第一个。我想在我的所有文件中都这样做。

示例:

function getBetween($content,$start,$end){
    $r = explode($start, $content);
    if (isset($r[1])){
        $r = explode($end, $r[1]);
        return $r[0];
    }
    return '';
}

$document = '<a data-id="777777"></a><a data-id="888888"></a><a data-id="99999"></a>';
$content = $document;
$start = '<a data-id="';
$end = '"';
$data = getBetween($content,$start,$end);
echo $data;

$document2 = '<a data-A="AAAAAA"></a><a data-A="BBBBBB"></a><a data-A="CCCCCC"></a>';
$content = $document2;
$start = '<a data-A="';
$end = '"';
$data2 = getBetween($content,$start,$end);
echo $data2;

现在它只提取777777 AAAAA。但我想要的是777777 AAAAAA 888888 BBBBBB 999999 CCCCC

3 个答案:

答案 0 :(得分:2)

代码:(Demo

function getBetween($content,$start,$end){
    return preg_match_all('/'.preg_quote($start,'/').'\K[^'.preg_quote($end,'/').']*(?='.preg_quote($end,'/').')/',$content,$out)?$out[0]:'';
}


$document = '<a data-id="777777"></a><a data-id="888888"></a><a data-id="99999"></a>';
$content = $document;
$start = '<a data-id="';
$end = '"';
$data = getBetween($content,$start,$end);
var_export($data);

$document2 = '<a data-A="AAAAAA"></a><a data-A="BBBBBB"></a><a data-A="CCCCCC"></a>';
$content = $document2;
$start = '<a data-A="';
$end = '"';
$data2 = getBetween($content,$start,$end);
var_export($data2);

输出:

array (
  0 => '777777',
  1 => '888888',
  2 => '99999',
)array (
  0 => 'AAAAAA',
  1 => 'BBBBBB',
  2 => 'CCCCCC',
)

我的方法有效地生成了这种模式:/<a data-id="\K[^"]*(?=")/,它返回所需的子串作为全字符串匹配。此模式不仅执行较少的步骤,因为它没有捕获组,它返回较小的结果数组。 Pattern Demo Link

preg_quote()用于转义所有必需的字符,以便变量模式不会“中断”。

$end在模式中使用了两次 - 一次在“否定字符类”[^"]中,第二次在“正向前瞻”中(?=")

仅供记录:

  • /"([^"]*)"/将处理您的示例输入。
  • 处理html字符串时,建议使用html解析器:DomDocument等。

*重要的是,我的模式仅用于处理$end作为单个字符。如果它不止一个字符,那么该模式将无法按预期工作,需要进行修改。

这是一个稍慢的模式/ preg_match()调用,允许更大的$end字符串:(Pattern Demo

preg_match_all('/'.preg_quote($start,'/').'\K.*?(?='.preg_quote($end,'/').')/',$content,$out)?$out[0]:'';

答案 1 :(得分:2)

只需使用preg_match_all功能。

示例:

<?php
$document = '<a data-id="777777"></a><a data-id="888888"></a><a data-id="99999"></a>';
$document2 = '<a data-A="AAAAAA"></a><a data-A="BBBBBB"></a><a data-A="CCCCCC"></a>';

$list1 = [];
$list2 = [];
preg_match_all('/<a data-id="([^"]+)"/', $document, $list1);
preg_match_all('/<a data-A="([^"]+)"/', $document2, $list2);
print_r([$list1, $list2]);

答案 2 :(得分:0)

我担心您的样本输入与您的实际输入很差,因此很难猜测您实际需要的准确性水平。

我将放弃不依赖正则表达式手术的高度稳定的技术。请注意,data-属性在有效的html文档中应该全部小写。

代码:(Demo

function getValue($html, $tag, $attr) {
    $dom = new DOMDocument; 
    $dom->loadHTML($html);
    $xpath = new DOMXPath($dom);
    $result = [];
    foreach ($xpath->query("//{$tag}[@{$attr}]") as $node) {
        $result[] = $node->getAttribute($attr);
    }
    return implode(',', $result);
}

$html = '<a data-id="777777"></a><a data-id="888888"></a><a data-id="99999"></a>';
$tag = 'a';
$attr = 'data-id';
echo getValue($html, $tag, $attr);

echo "\n---\n";

$html = '<a data-A="AAAAAA"></a><a data-A="BBBBBB"></a><a data-A="CCCCCC"></a>';
$tag = 'a';
$attr = 'data-a';
echo getValue($html, $tag, $attr);

输出:

777777,888888,99999
---
AAAAAA,BBBBBB,CCCCCC