当不在双引号内时替换

基本上我想用句子替换某些单词(例如单词“树”与单词“pizza”)。 限制:当应该替换的单词在双引号之间时,不应执行替换。

例:

The tree is green. -> REPLACE tree WITH pizza
"The" tree is "green". -> REPLACE tree WITH pizza
"The tree" is green. -> DONT REPLACE
"The tree is" green. -> DONT REPLACE
The ""tree is green. -> REPLACE tree WITH pizza

有没有可能用正则表达式来做到这一点? 我会计算单词前双引号的数量,并检查它是奇数还是偶数。 但是,这可能在PHP中使用preg_replace?

谢谢!

//编辑:

目前我的代码如下所示:

preg_replace("/tree/", "pizza", $sentence)

但是这里的问题是用双引号实现逻辑。 我尝试了这样的事情:

preg_replace("/[^"]tree/", "pizza", $sentence)

但这不起作用,因为它只检查单词前面是否有双引号。 但是上面有这个检查失败的例子。 导入是我只想用正则表达式解决这个问题。


正则表达式不是一种可以满足每项工作需要的工具。 您可以在某种程度上使用正则表达式,但对于嵌套引号中的所有情况,它会继续变得更加复杂。

你可以在这里使用负面预测

$text = preg_replace('/btreeb(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/i', 'pizza', $text);

请参阅Working demo

正则表达式:

b               the boundary between a word char (w) and not a word char
 tree            'tree'
b               the boundary between a word char (w) and not a word char
(?!              look ahead to see if there is not:
 [^"]*           any character except: '"' (0 or more times)
  "              '"'
 (?:             group, but do not capture (0 or more times)
  (?:            group, but do not capture (2 times):
   [^"]*         any character except: '"' (0 or more times)
    "            '"'
  ){2}           end of grouping
 )*              end of grouping
 [^"]*           any character except: '"' (0 or more times)
 $               before an optional n, and the end of the string
)                end of look-ahead

另一个选择是使用控制回溯,因为你可以在php中执行此操作

$text = preg_replace('/"[^"]*"(*SKIP)(*FAIL)|btreeb/i', 'pizza', $text);

请参阅Working demo

这个想法是跳过引用中的内容。 我首先匹配引号后跟任何字符,除了"后跟引号”,然后使子模式失败并强制正则表达式引擎不使用(*SKIP)(*FAIL)回溯控制动词重试子字符串。


有一个方便的技巧使用一些隐藏的正则表达式的权力:

~".*?"(*SKIP)(*FAIL)|btreeb~s

说明:

~                   # start delimiter (we could have used /, #, @ etc...)
"                   # match a double quote
.*?                 # match anything ungreedy until ...
"                   # match a double quote
(*SKIP)(*FAIL)      # make it fail
|                   # or
btreeb            # match a tree with wordboundaries
~                   # end delimiter
s                   # setting the s modifier to match newlines with dots .

在实际的PHP代码中,您希望使用preg_quote()来转义正则表达式字符。 这是一个小片段:

$search = 'tree';
$replace = 'plant';
$input = 'The tree is green.
"The" tree is "green".
"The tree" is green.
"The tree is" green.
The ""tree is green.';

$regex = '~".*?"(*SKIP)(*FAIL)|b' . preg_quote($search, '~') . 'b~s';
$output = preg_replace($regex, $replace, $input);
echo $output;

在线正则表达式演示 在线PHP演示


这个使用前瞻来匹配tree

$pattern = '~btreeb(?=([^"]|("[^"]*"))*$)~im';

$str = '
The tree is green. -> REPLACE tree WITH pizza
"The" tree is "green". -> REPLACE tree WITH pizza
"The tree" is green. -> DONT REPLACE
"The tree is" green. -> DONT REPLACE
The ""tree is green. -> REPLACE tree WITH pizza';

echo "<pre>".preg_replace($pattern,"pizza",$str)."</pre>";

它查找tree ,如果找到,只匹配它,如果后面跟有字符,不是双引号[^"]或引用组"[^"]*"直到使用修饰符i(PCRE_CASELESS)和m PCRE_MULTILINE)。

我不想吃绿色的披萨! 圣诞快乐 :-)

链接地址: http://www.djcxy.com/p/69553.html

上一篇: replace when not inside double quotes

下一篇: My web page is fine on my server, but my local copy gives a parser error