字符串缺失分隔符上的单个捕获组的PCRE正则表达式

时间:2018-04-17 19:51:17

标签: php regex

我有这种节点值的html:

80% Polyester 10% Cotton 10% Rayon

它也可以是这样的:

90% Cotton 10% Rayon

或者:

100% Cotton

编辑 - 还要捕获的文字可能不止一个字,如:

90% Egyptian Cotton 10% Polyester

我需要在PHP中做的是将其更改为:

<li>80% Polyester</li>
<li>10% Cotton</li>
<li>10% Rayon</li>

我不确定如何让捕获组完全正确...也许需要有两个捕获组可以发生1次以上?

preg_match('/<p>([1-9]?[0-9]?% [^\d<]+|^100% )+<\/p>/', '<p>80% Polyester 10% Cotton 10% Rayon</p>', $matches);

这只找到1个匹配:10%Rayon ...我错误的是它不能捕获所有3个组?

编辑:请忘记HTML标记

我从问题中剥离了标签,因为人们无法克服整个正则表达式和HTML问题......请将此视为数据字符串。

3 个答案:

答案 0 :(得分:2)

您可以使用此preg_replace

$repl = preg_replace('/([\d.]+%\h*\pL+(?:\h+\pL+)*)\h*/', 
                     '<li>$1</li>\n', $str);

RegEx Demo

([\d.]+%\h*\pL+(?:\h+\pL+)*)\h*匹配并分组1+位后跟%,后跟0 +空格,后跟1个字母和空格字符。

答案 1 :(得分:1)

您需要先输入分隔结构,然后才能在新找到的字符串上使用正则表达式。这可以使用preg_replace_callback完成。

echo preg_replace_callback('/<p>(.+?)<\/p>/', function($match) {
    if(preg_match_all('/\d+%\h+\D+/', $match[1], $newmatch)) {
        $temp = '';
        foreach($newmatch[0] as $li) {
            $temp .= '<li>' . $li . '</li>';
        }
        return $temp;
    }
}, '<p>80% Polyester 10% Cotton 10% Rayon</p>');

演示:https://3v4l.org/rQKL5

您还可能希望将\D+更改为[a-zA-Z]+或其他内容,具体取决于百分比单位的标签。

答案 2 :(得分:0)

如果这是你的字符串,那么我根本不明白为什么你需要正则表达式 你可以使用explode使它成为一个数组,并使用array_chunk循环它以获得当时的两个项目(百分比和材料)。

$str = "80% Polyester 10% Cotton 10% Rayon";

Foreach(array_chunk(explode(" ", $str),2) as $material){
    Echo "<li>" . Implode(" ", $material) . "</li>\n";
}

输出:

<li>80% Polyester</li>
<li>10% Cotton</li>
<li>10% Rayon</li>

https://3v4l.org/pE9NI