【问题标题】:How to replace words outside double and single quotes如何替换双引号和单引号之外的单词
【发布时间】:2012-06-11 08:06:16
【问题描述】:

对于 PHP 中的自定义脚本解析器,我想替换包含双引号和单引号的多行字符串中的一些单词。 但是,只能替换引号之外的文本。

Many apples are falling from the trees.    
"There's another apple over there!"    
'Seedling apples are an example of "extreme heterozygotes".'

例如,我想将 'apple' 替换为 'pear',但仅限于引号句子之外。所以在这种情况下,只有“许多苹果从树上掉下来”中的“苹果”才会成为目标。

以上将给出以下输出:

Many pears are falling from the trees.    
"There's another apple over there!"    
'Seedling apples are an example of "extreme heterozygotes".'

我怎样才能做到这一点?

【问题讨论】:

  • 您能否发布您的 PHP 解析脚本,以便我们提出修改建议。

标签: php string preg-replace


【解决方案1】:

这个函数可以解决问题:

function str_replace_outside_quotes($replace,$with,$string){
    $result = "";
    $outside = preg_split('/("[^"]*"|\'[^\']*\')/',$string,-1,PREG_SPLIT_DELIM_CAPTURE);
    while ($outside)
        $result .= str_replace($replace,$with,array_shift($outside)).array_shift($outside);
    return $result;
}

它是如何工作的 它由带引号的字符串分割,但包括这些带引号的字符串,这使您可以在一个数组中交替使用非引用、引用、非引用、引用等字符串(一些非引用引用的字符串可能为空)。然后它在替换单词和不替换之间交替,因此只替换未引用的字符串。

以你的例子

$text = "Many apples are falling from the trees.    
        \"There's another apple over there!\"    
        'Seedling apples are an example of \"extreme heterozygotes\".'";
$replace = "apples";
$with = "pears";
echo str_replace_outside_quotes($replace,$with,$text);

输出

Many pears are falling from the trees.    
"There's another apple over there!"    
'Seedling apples are an example of "extreme heterozygotes".'

【讨论】:

  • 我无法让first answer 中使用的正则表达式可靠地工作,所以我创建了这个函数,它总是可以工作。
  • 我测试了您的脚本并发现了一个错误。如果您的字符串中有转义字符 \' 或 \" ,它将提前关闭导致不可预测的结果。此正则表达式修复它 /('(?:[^\\\\']+|\\\(\\\ \\\\)*.)*'|\"(?:[^\\\\\"]+|\\\(\\\\\\\)*.)*\")/ .它不漂亮,但它有效。必须有一个更优雅的解决方案,但我现在不能在这上面浪费更多时间。
  • 正如 Dieter 所说,示例代码不适用于以下情况:$test="x('\'y');y(1);console(\"xyz\",xyz); echo "<LI>".$this->str_replace_outside_quotes("y", "z", $test); 但使用 Dieters 版本确实有效
【解决方案2】:

我想出了这个:

function replaceOutsideDoubleQuotes($search, $replace, $string) {
    $out = '';
    $a = explode('"', $string);
    for ($i = 0; $i < count($a); $i++) {
        if ($i % 2) $out .= $a[$i] . '"';
        else $out .= str_replace($search, $replace, $a[$i]) . '"';
    }
    return substr($out, 0, -1);
}

逻辑是:你用双引号分解字符串,所以返回的字符串数组的 odd 元素表示引号外的文本,even 表示里面的文本双引号。

那么,您可以交替连接原始部件和替换部件来构建输出,好吗?

此处的工作示例:http://codepad.org/rsjvCE8s

【讨论】:

  • 谢谢,但它只适用于双引号......我需要只替换双引号和单引号之外的东西:)
【解决方案3】:

只是一个想法:通过删除引用部分创建一个临时字符串,替换您需要的部分,然后添加您删除的引用部分。

【讨论】:

  • 如何将引用的部分重新添加到原始字符串的原始位置?
【解决方案4】:

可以使用preg_replace,用正则表达式替换“”里面的单词

$search  = array('/(?!".*)apple(?=.*")/i');
$replace = array('pear');
$string  = '"There\'s another apple over there!" Seedling apples are an example of "extreme heterozygotes".';

$string = preg_replace($search, $replace, $string);

您可以通过在 $search 中添加另一个 RegEx 并在 $replace 中添加另一个替换字符串来添加更多可能的可搜索对象

这个 RegEx 使用前瞻和后瞻来确定搜索到的字符串是否在 " " 内

【讨论】:

  • 对不起,我刚刚注意到我读错了问题 - 提出了相反的问题。我会改变它...
  • 它似乎与问题的要求相反,将文本替换为 inside 引号,而不是外部。
猜你喜欢
  • 1970-01-01
  • 2020-07-11
  • 2018-11-18
  • 2011-01-26
  • 1970-01-01
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多