如果在执行字符串 Replacement/Removal 时在引号中,则跳过 Words/Phrases

Skip Over Words/Phrases if In Quotes while doing String Replacement/Removal

假设我有这样一个字符串

I am flying from "Detroit to Vancouver" this July

$string = 'I am flying from "Detroit to Vancouver" this July';

我还有一组“stopwords”(我选择从 string/strings 中删除的单词)

$stopwords = array( "to", "anotherstopword", "andanother" )

目前我正在使用

$string = str_replace($stopwords, ' ', $string);

这当然给了我string(33) "I am flying from "Detroit Vancouver" this July"

我正在考虑在 str_replace 之前用 space 分解 $string,给我类似

的东西
Array
(
    [0] => I
    [1] => am
    [2] => flying
    [3] => from
    [4] => "Detroit
    [5] => to
    [6] => Vancouver"
    [7] => this
    [8] => July
)

然后也许从数组中删除它们,进行替换,然后重新插入它们..但这似乎有点过分了

我也想过使用这样的函数

  function getStringBetween($str, $from, $to, $withFromAndTo = false)
  {
      $sub = substr($str, strpos($str, $from) + strlen($from), strlen($str));
      if ($withFromAndTo)
          return $from . substr($sub, 0, strrpos($sub, $to)) . $to;
      else
          return substr($sub, 0, strrpos($sub, $to));
  }

这样做时,

    echo '<pre>';
    print_r(getStringBetween($string, '"', '"'));
    echo '</pre>';

输出:

Detroit to Vancouver

并在 str_replace 之前执行某种忽略条件..

但是只要字符串中有多个引号,这就会失败..

理想情况下,我想创建一个条件,如果字符串包含双引号,则在 str_replace 过程中完全忽略它们。

我当然不反对使用 str_replace 以外的东西,比如 preg_replace,但我没有足够的经验来为我的预期输出生成样本。

谁能想出一个好方法来忽略停止 words/words 在进行替换之前删除?

编辑:

代码示例

<?php

  $stopwordstest = array( " to ", " a ", " test " );

  $string = 'I am flying from "Detroit to Vancouver" this July when the weather is test nice';

  var_dump($string);

// as is, without string replace
// string(79) "I am flying from "Detroit to Vancouver" this July when the weather is test nice" 

  $string = str_replace($stopwordstest, ' ', $string);

  echo '<br><br>';

  var_dump($string);

// string(71) "I am flying from "Detroit Vancouver" this July when the weather is nice"

// Expected output is:
//
// string(74) "I am flying from "Detroit to Vancouver" this July when the weather is nice"
//

?>

换句话说,我希望字符串替换按预期进行,但由于单词 to 包含在引号 ("Detroit to Vancouver") 中,它应该跳过这个单词,因为它在引号中。

foreach ($stopwords as &$stopword) {
    $string = str_replace($stopword, ' ', $string);
}

使用正则表达式会很容易,使用 PHP (PCRE) 会更容易。使用 PCRE,您可以使用 (*SKIP) 回溯动词来匹配和跳过。您匹配一个双引号字符串,然后让引擎从整体匹配中跳过这部分,并在交替的第二侧键入您想要的模式。

"[^"\]*(?:\.[^"\]*)*"(*SKIP)(*F)

上面的正则表达式匹配双引号字符串(包括转义的双引号)然后告诉引擎忘记。

这将是 PHP 实现此功能并在正则表达式中收集停用词的代码:

echo preg_replace('/"[^"\\]*(?:\\.[^"\\]*)*"(*SKIP)(*F)|\b(?:'
    . implode('|', array_map('preg_quote', $stopwords))
    . ')\b\h*/', '', $string);

Live demo