使用 PHP 将文本替换为preg_match_all

Replace text with preg_match_all using PHP

提问人:Shibbir 提问时间:3/7/2023 最后编辑:ADysonShibbir 更新时间:3/7/2023 访问量:70

问:

我有这个字符串:

The product title is [title] and the price is [price] and this product link is [link]

我有一个名为 whch 包含相关数组的变量。$get_product

现在,我想用变量键替换字符串中的 [xxx]。我正在做什么:$get_product[xxx]

$pattern = '/\[(.*?)\]/';
preg_match_all($pattern, $optimization_prompt, $matches);

if( $matches ) {
    foreach( $matches as $key => $match ) {
        for( $i = 0; $i < count($match); $i++ ) {
            if( preg_match_all($pattern, $match[$i], $matches)  ) {
                // with bracket 
                $remove_bracket         = trim( $match[$i], '[]');
                $optimization_prompt    = str_replace( $match[$i], isset( $get_product[$remove_bracket] ) ? $get_product[$remove_bracket] : '', $optimization_prompt);
            } else {
                // Without bracket
                $remove_bracket         = trim( $match[$i], '[]');
                $optimization_prompt    = str_replace( $match[$i], '', $optimization_prompt);
            }
        }
    }
}

它返回了我:

<pre>The product  is  Infaillible Full Wear327 Cashm and the  is  10.49  and this product  is  https://www.farmaeurope.eu/infaillible-full-wear327-cashm.html</pre>

结果是可以的,但它删除了称为标题、价格链接的实际文本

PHP 正则表达 Preg-Match

评论

0赞 Luuk 3/7/2023
为什么要去掉括号,然后问为什么实际的文本被替换了?
0赞 Shibbir 3/7/2023
我去掉括号来获取括号值,以便从 $get_product 变量中获取键值
0赞 Shibbir 3/7/2023
像这样从我要替换的变量中获取值。$get_product[$remove_bracket]
0赞 Luuk 3/7/2023
好吧,让我改写一下,你在分支中替换了什么?(带有注释“不带括号”的那个)?else
0赞 Shibbir 3/7/2023
@Luuk我在想别的事情,但忘记了这个其他块。我的总体目标是用值替换。[xxx]$get_product[xxx]

答:

0赞 Luuk 3/7/2023 #1

添加一些调试行应该会有所帮助:

<?php

$optimization_prompt = 'The product title is [title] and the price is [price] and this product link is [link]';
$get_product = [ "title"=>"TITLE", "price"=>"PRICE", "link"=>"LINK"];

$pattern = '/\[(.*?)\]/';
preg_match_all($pattern, $optimization_prompt, $matches);

if( $matches ) {
    foreach( $matches as $key => $match ) {
        for( $i = 0; $i < count($match); $i++ ) {
            if( preg_match_all($pattern, $match[$i], $matches)  ) {
                // with bracket 
                $remove_bracket         = trim( $match[$i], '[]');
                print "WITH Replace -$match[$i]-:". (isset( $get_product[$remove_bracket] ) ? $get_product[$remove_bracket] : '').":" .PHP_EOL;
                $optimization_prompt    = str_replace( $match[$i], isset( $get_product[$remove_bracket] ) ? $get_product[$remove_bracket] : '', $optimization_prompt);
            } else {
                // Without bracket
                $remove_bracket         = trim( $match[$i], '[]');
                print "WITHOUT Replace -$match[$i]-: ". '' .":".PHP_EOL;
                $optimization_prompt    = str_replace( $match[$i], '', $optimization_prompt);
            }
        }
    }
}

print $optimization_prompt;

输出:

WITH Replace -[title]-:TITLE:
WITH Replace -[price]-:PRICE:
WITH Replace -[link]-:LINK:
WITHOUT Replace -title-: :
WITHOUT Replace -price-: :
WITHOUT Replace -link-: :
The product  is TITLE and the  is PRICE and this product  is LINK

这里:表示 之间的文本被 之间的文本所取代,有效地删除了文本。WITHOUT Replace -title-: :-:title

1赞 Destroy666 3/7/2023 #2

我不知道你想在那里做什么,但它似乎完全太复杂了。这是一个带有注释的简单解决方案:

$pattern = '/\[.*?\]/';
$get_product = ['title' => 'answer', 'price' => 666, 'link' => 'https://stackoverflow.com'];
$optimization_prompt = 'The product title is [title] and the price is [price] and this product link is [link]';
preg_match_all($pattern, $optimization_prompt, $matches);

// Cycle through full matches
foreach($matches[0] as $match) {
    // Remove the brackets for the array key
    $product_key = trim($match, '[]');
    
    // If product key available, replace it in the text
    $optimization_prompt = str_replace($match, $get_product[$product_key] ?? '', $optimization_prompt);
}

// Result: The product title is answer and the price is 666 and this product link is https://stackoverflow.com
echo $optimization_prompt;

评论

0赞 Shibbir 3/7/2023
哇,太棒了。它似乎更容易的版本。
1赞 RiggsFolly 3/7/2023 #3

如果你看一下你的第一个结果,你会发现你在数组中拥有了你需要的一切preg_match_all()$matches

数组$matches

Array
(
    [0] => Array
        (
            [0] => [title]
            [1] => [price]
            [2] => [link]
        )

    [1] => Array
        (
            [0] => title
            [1] => price
            [2] => link
        )

)

因此,您可以将代码简化为

$get_product = ['title' => '>This is a TITLE<', 
                'price' => '>£10000.99<', 
                'link' => '>http:stackoverflow.com<'
    ];
$optimization_prompt = 'The product title is [title] and the price is [price] and this product link is [link]';

$pattern = '/\[(.*?)\]/';

preg_match_all($pattern, $optimization_prompt, $matches);
print_r($matches);

foreach( $matches[0] as $i => $replace ) {
    $optimization_prompt = str_replace( $replace, $get_product[$matches[1][$i]], $optimization_prompt);
}

echo $optimization_prompt;

结果是

The product title is >This is a TITLE< and the price is >£10000.99< and this product link is >http:stackoverflow.com<
2赞 Casimir et Hippolyte 3/7/2023 #4

这不是一份工作,而是preg_replace_callback的工作(这是一项替代任务,是还是不是?preg_match_all

$get_product = ['title' => 'theTitle', 'price' => 45, 'link' => 'https://thelink.com'];

$result = preg_replace_callback(
    '~\[([^][]+)]~',
    fn($m) => $get_product[$m[1]] ?? $m[0],
    $optimization_prompt
);

演示

该模式使用捕获组(捕获组 1)提取方括号之间的内容。的第二个参数是回调函数,用于测试捕获的内容是否作为键存在于数组中,并返回相应的值或完全匹配。preg_replace_callback$m[1]$get_product$m[0]


另一种方式根本没有正则表达式(因为您正在寻找文字字符串):

$get_product = ['title' => 'theTitle', 'price' => 45, 'link' => 'https://thelink.com'];

$result = str_replace(
    array_map(fn($k) => "[$k]", array_keys($get_product)),
    $get_product,
    $optimization_prompt
);

演示