PHP preg_replace: 查找不以感叹号开头的字符串部分

PHP preg_replace: find string part not starting with an exclamation point

我正在处理一些非常混乱的 Excel sheets,并试图使用 PHP 寻找线索..

我有一个 MySQL 数据库,其中包含 excel 文档中的所有公式,并且像往常一样,当前 sheet 中的单元格名称没有 "sheetname!"它的前面。为了使其可搜索(并在公式中找到死路),我喜欢用 sheetname 作为前缀替换数据库中的所有公式。

示例:

=+(sheet_factory_costs!A17/sheet_employees!D23)+T12+W12

数据库包含当前 sheet 的名称,我想用 sheet 名称更改上面的公式(我们称之为 "sheet_turnover")。

=+(sheet_factory_costs!A17 / sheet_employees!D23)+sheet_turnover!T12+sheet_turnover!W12

我在 PHP 中尝试使用 preg_replace,我想我需要以下规则:

  1. 找到一个或两个字母,紧跟一个数字。这始终是公式中的单元格地址。
  2. 当有!在之前的位置上,已经有一个sheet名称。所以我只查找不以感叹号开头的字母和数字。

问题似乎是!也是模式中的特殊符号。即使我试图逃避它,它也不起作用:

$newformula = 
preg_replace('/(?<\!)[A-Z]{1,2}[0-9]/', 
'lala', 
$oldformula);

(lala 是我的临时标记,用于查看它是否选择了正确的单元格地址)

(是的,lala 仅位于第一个数字之上,但现在这不是问题)

(是的,所有 Excel $..$..(永久)标记都已被替换。无需在公式中构建它)

您的负向回顾已损坏,您需要将其定义为 (?<!!)。但是,您还需要在它之前使用单词边界,或者使用 (?<![A-Z]) 后视以确保在 [A-Z]{1,2}.

之前没有其他字母

所以,您可以使用

'~\b(?<!!)[A-Z]{1,2}[0-9]~'

regex demo。替换为 sheet_turnover![=15=],其中 [=16=] 是整个匹配值。

详情

  • \b - 单词边界(这是必要的,否则 name!AA11 仍会匹配)
  • (?<!!) - 没有!紧靠当前位置
  • 的左侧
  • [A-Z]{1,2} - 1 或 2 个字母
  • [0-9] - 一个数字。

另一种方法是匹配并跳过 "wrong" 上下文,然后匹配并保留 "right" 上下文:

'~\w+![A-Z]{1,2}[0-9](*SKIP)(*F)|\b[A-Z]{1,2}[0-9]~'

参见 this regex demo

此处,\w+![A-Z]{1,2}[0-9](*SKIP)(*F)| 部分匹配 1 个或多个字符,然后是 1 或 2 个大写 ASCII 字母,然后是数字,(*SKIP)(*F) 将忽略匹配并使引擎继续查找上一场比赛结束后的比赛。