【问题标题】:php - preg_replace non-matched characters except matched stringsphp - preg_replace 除匹配字符串外的不匹配字符
【发布时间】:2016-01-02 23:47:48
【问题描述】:

我有这样的字符串:

// example
$str1 = "     10.503 GB  3.4 GiB   ";
$str2 = "  40.29 KiB    ";
$str3 = "14.3 GB    2.1 51   ";

这是我的正则表达式,分别匹配字符串“10.503 GB”、“3.4 GiB”、“40.29 KiB”和“14.3 GB”

$regex = '/(\d+\.\d+ [A-Za-z]+[^\s])/';
preg_match_all($regex, $str1, $out1);
preg_match_all($regex, $str2, $out2);
preg_match_all($regex, $str3, $out3);

所以问题是,我如何用用户定义的字符替换与我的正则表达式模式不匹配的非匹配字符?示例如下:

$char = 'A'; // assume this is user input
$str1 = "     10.503 GB  3.4 GiB   ";
$str2 = "  40.29 KiB    ";
$str3 = "14.3 GB    2.1 51   ";

/* preg_replace (or another preg_* magic here */

所以最后的字符串是

$str1 = "AAAAA10.503 GBAA3.4 GiBAAA";
$str2 = "AA40.29 KiBAAAA";
$str3 = "14.3 GBAAAAAAAAAAAAA";

我知道不使用 preg_replace 的解决方案,但只是假设 preg_replace 在这里是必要的(或者如果您愿意,也可以使用另一个 preg_*)

所以有可能吗?如果是,我该怎么做?

【问题讨论】:

  • 如果不是PHP,还需要支持什么引擎?我想这个问题已经回答了。只有 Boost 可以使用条件替换模式正确地完成这项工作,其他的会产生不精确的输出(在每个不匹配之后有一个额外的 A)。看看另一个PHP regex demo
  • @Casimir et Hippolyte 对我的问题给出了完美的答案 :) 也感谢 stribizhev 提供信息!

标签: php regex preg-replace


【解决方案1】:

类似:

~\d+\.\d+ [a-zA-Z]+\b(*SKIP)(*F)|.~

用 A 代替。

demo

(*SKIP) 强制在模式失败后不重试先前匹配的位置。 (*F)(*FAIL) 强制模式失败。

请注意,要处理不带小数的值,应将\d+\.\d+ 替换为\d+(?:\.\d+)?


如果您不使用带有这些回溯控制动词的正则表达式引擎(仅适用于 Perl、使用 PCRE 的语言或新的 Python 正则表达式模块),您可以使用捕获组和反向引用来实现相同的目的:

pattern: ((?:\d+(?:\.\d+)? [a-zA-Z]+\b)*).
replacement: \1A
or: $1A

使用 PCRE、Perl、Python 正则表达式模块和 Ruby 2,您也可以这样做:

pattern: (?:\d+(?:\.\d+)? [a-zA-Z]+\b)*\K.
replacement: A

【讨论】:

  • 哇!当我看到 (SKIP) 和 (*FAIL) 时,我感到非常惊讶!但在我的进一步阅读中,这仅适用于 PHP 所依赖的 PCRE 引擎,但我如何在不依赖此功能的情况下完成此操作? (使用另一个正则表达式引擎的示例)*抱歉在这里提出另一个问题
  • @MohdShahril:我添加了一种没有回溯控制动词的方法,但请记住,通用正则表达式模式不存在,每种语言可能都有自己的正则表达式引擎,实现和语法。
  • 我明白了,但是您的一般正则表达式解决方案在 A 之间有一个间隙空间,这是不可避免的吗? regex101 demo
  • @MohdShahril:没有空格,这只是 regex101 显示结果的方式。 (确实有点奇怪)。
  • 我明白了,对此感到抱歉:(顺便说一句,你的答案是完美的!看起来它会感觉到我今天的整个差距,了解更多你的正则表达式是如何工作的 :D 感谢@Casimir et Hippolyte 的帮助大师,非常感谢!
猜你喜欢
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 2013-07-11
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多