2013-07-30 91 views
0

我有一个字符串,其中包含纯文本“[var-X]”的各种实例,其中X可以是任何正整数。我没有事先知道X可以在任何给定的脚本中有多高(但是如果需要,我可以得到它)。PHP - 用其他不同的字符串替换多个相似的字符串

这些[var-X]中的每一个都必须被评估并由不同的字符串替换。不同的字符串的值取决于一个外部的XML文件,我没有问题解析。

所以,我的问题是,如何从

$str = "Hey I am some text,[var-1] a lot of these [var-3] parts will have to [var-9] go away and 
be exchanged [var-2] by others"; 

去加(假设这个东西是一个更大的XML中)

(some xml...) 
<Variation id="1">really</Variation> 
<Variation id="2">quickly</Variation> 
<Variation id="3">strange</Variation> 
(some other xml...) 
<Variation id="9">definitely</Variation> 
(more xml...) 

$str = "Hey, I am some text, really a lot of these strange parts will have to definitely go away 
and be exchanged quickly by others"; 

是的最好的方法是首先遍历我的xml,找出整数有多高,然后用字符串上的strpos再次迭代?

我该如何处理可能发现[var-7]和[var-72](事先不知道数字长度)的事实?这可以用一个正则表达式来完成(假设一旦我把“[var-7]”和“7”作为一个整数,我仍然需要处理一些东西以知道替代它的位置)?

我希望问题清楚。我的不确定性主要是关于最好的方法,因为我可能能够一起攻击一些东西,但它可能是缓慢和丑陋的。

+0

@AndyJones我目前(在测试现在)的方法包括:strpos “[VAR-”,然后strpos下一个“]”并从与substr的位置差异中获取int值。评估它,根据需要进行替换。转到下一个“[var-”,直到该strpos返回FALSE。它只是觉得有点笨拙。 – user1989178

+0

gotcha - 建议使用preg_match和preg_replace - 我将添加一个答案然后 –

+0

您如何阅读XML? – federicot

回答

4

您可以使用 preg_replace_callback,它允许您使用函数作为替换。

$txt = preg_replace_callback('~\[var-(\d+)]~', function ($match) { 
    return $var[$match[1]]; 
}, $txt); 

如果要从XML文档中提取值,使用XPath是一种好方法。例如:

$str = "Hey I am some text,[var-1] a lot of these [var-3] parts will have" 
    . " to [var-9] go away and be exchanged [var-2] by others"; 

$xml = <<<'LOD' 
<?xml version="1.0"?> 
<Variations> 
    <Variation id="1">really</Variation> 
    <Variation id="2">quickly</Variation> 
    <Variation id="3">strange</Variation> 
    <Variation id="9">definitely</Variation> 
</Variations> 
LOD; 

$doc = new DOMDocument(); 
@$doc->loadXML($xml); 
$xpath = new DOMXPath($doc); 

$callback = function ($match) use ($xpath) { 
    $var_node = $xpath->query("/Variations/Variation[@id='" 
          . $match[1] . "']/text()")->item(0); 
    $var_content= $var_node->nodeValue; 
    return $var_content; 
}; 

$str = preg_replace_callback('~\[var-(\d+)]~', $callback, $str); 
+0

据我的理解,preg_replace_callback被称为每一个匹配,是否正确?如果是这样,我想我已经找到了我的答案,并感谢你:)编辑:这一切都检查出来,再次感谢。 – user1989178

+0

@ user1989178:是的,情况就是这样。为什么不使用XPath查询来提取回调函数中需要的值? –

+0

我很乐意这样做,但是我不熟悉XPath现在已经足够了解它了......另外,XML中的一些attrs需要根据会话变量进行分析和评估,我不确定这是非常实用的。 – user1989178

2

最好的办法是使用preg_replace_callback。在下面的代码中,我直接使用你的数组,但是你说你想从xml读取数据,所以你的逻辑读取它将取代简单的数组访问。如果索引不符合xml中的任何内容,您可能还想考虑想做什么。在下面的例子中,我假设你根本不想取代它,但这取决于你。

$str = "Hey I am some text,[var-1] a lot of these [var-3] parts will have to [var-9] go away and be exchanged [var-2] by others"; 


$var[1] = "really"; 
$var[2] = "quickly"; 
$var[3] = "strange"; 
$var[9] = "definitely"; 

$done = preg_replace_callback('/(?P<original>\[var-(?P<index>\d+)\])/', function($match) use($var) { 
    return isset($var[$match['index']]) ? $var[$match['index']] : $match['original']; 
}, $str); 

echo $done; 
+0

谢谢,这澄清了答案,如果我有这样的可能性(我现在显然做!),我会upvote你 – user1989178

+0

太棒了!确保你不要忘记关闭中的“使用”部分。否则'$ var'在该函数的范围内将不可用。 – wkjagt

0

如果你想避免使用preg_replace_callback你可以这样做:

while(preg_match('/\[var-(\d+)\]/', $str, $m)){ 
    $str = preg_replace('/\[var-' . $m[1] . '\]/', $var[$m[1]], $str); 
} 
相关问题