【问题标题】:How to replace a regex pattern with a regex pattern?如何用正则表达式模式替换正则表达式模式?
【发布时间】:2012-02-12 18:48:18
【问题描述】:

我因为无法弄清楚这一点而感到非常愚蠢,但我就是无法弄清楚。我需要用模式替换正则表达式字符串,我找到了两个这样做的例子,但老实说,它们让我比以往任何时候都更加困惑。

这是我目前的尝试:

$string = '26 14:46:54",,"2011-08-26 14:47:02",8,0,"BUSY","DOCUMENTATION","1314370014.18","","","61399130249","7466455647","from-internal","""Oh Snap"" <61399130249>","SIP/1037-00000014","SIP/CL-00000015","Dial","SIP/CL/61436523277,45","2011-08-26 14:47:06","2011-08-26 14:47:15","2011-08-26 ';
$pattern = '["SIP/CL/\d*?,\d*?",]';
$replacement = '"SIP/CL/\1|\2",';
$string = preg_replace($pattern, $replacement, $string);
print($string);

但这只是将\1\2 替换为空白。所以很明显我没有理解整个概念。

我最后想要的是改变:

this: "SIP/CL/61436523277,45"
to: "SIP/CL/61436523277|45"

格式不佳的 CSV 中的逗号会影响我的其他一些脚本。

【问题讨论】:

  • 它的格式似乎不是很差,因为它在引号之间...您确实为此使用了fgetcsv,不是吗?或者 str_getcsv 如果它是一个字符串。
  • 我不是,但我现在是。无论如何,我需要学习这种形式的正则表达式替换。所以用一块石头杀死了两只鸟:)。我知道 fgetcsv,但它不适合我的目的(它是 1.8GB+ csv....,无法将其全部加载到内存中),但 str_getcsv 运行良好! :)
  • 好的,供将来参考:fgetcsv 也不会将整个文件读入内存,只是逐行读取;)

标签: php regex csv match


【解决方案1】:

你缺少大括号,模式应该是这样的:

$pattern = '["SIP/CL/(\d*),(\d*)",]';

【讨论】:

  • 就这样?我觉得自己像个傻瓜。非常感谢 :) 效果很好。
  • 您已经通过在括号之外更改了非灰色运算符的含义。应该是 (\d+?)
  • @user1130968 将最有用的答案标记为答案是在此表示感谢的最佳方式。)(FAQ 也是如此)
  • @meouw 你说得对,我没有注意到我只是添加了大括号我根本不会使用它
  • 最终看起来像 $pattern = '["SIP/CL/(\d*),(\d*)",]'; $replacement = '"SIP/CL/\1|\2,"';
【解决方案2】:

$replacement 中的反向引用 \1\2 旨在引用 $pattern 中的捕获的组。捕获的组通过在它们周围放置括号来保存()

尝试(我将您的正则表达式分隔符 [] 更改为 ! 等待下面 cmets 的回答):

$pattern = '!"SIP/CL/(\d*?),(\d*?)",!';
$replacement = '"SIP/CL/\1|\2",';

另请注意,由于您的 $pattern 后面有逗号,因此如果您的 $string"SIP/CL/61436523277,45" 结尾,则不会转换。我建议删除结尾的逗号。

此外,您当前的正则表达式会将"SIP/CL/," 转换为"SIP/CL/|"。如果这不是您的意图,请将\d(即0 个或多个匹配项)之后的* 更改为+(一个或多个匹配项)。

【讨论】:

  • [ 和 ] 在这种情况下将被视为分隔符,而不是字符类
  • 模式 1 不会是 SIP/CL/{numbershere} 所以你应该想要'"SIP/CL/(\d*?),(\d*?)",' 否则你的第一个参考很有趣。如您的替换将是SIP/CL/SIP/CL/numbershere|numbersagain
  • @meouw,我忘了,干杯。但是不应该是[[]]而不是[]吗?
  • PHP 和 Perl 一样,将正确配对的括号识别为分隔符,因此 [](){}&lt;&gt; 都可以工作。我认为在 PHP 中使用它们是个坏主意。令人困惑的是,与 Perl 不同,您必须使用正则表达式分隔符 除了 引号。至少,任何查看您的代码的人都会想知道是否理解它为什么有效。 ;)
【解决方案3】:

我认为你需要这个:

$pattern = '["SIP/CL/(\d+),(\d+)",]';

括号 - () - 捕获内部的匹配,允许您在替换模式中引用它。

您还可以通过扩展匹配模式中的捕获来简化替换模式:

$pattern = '[("SIP/CL/\d+),(\d+",)]';   
$replacement = '\1|\2';

【讨论】:

    【解决方案4】:

    我做了这个

    $string = '26 14:46:54",,"2011-08-26 14:47:02",8,0,"BUSY","DOCUMENTATION","1314370014.18","","","61399130249","7466455647","from-internal","""Oh Snap"" <61399130249>","SIP/1037-00000014","SIP/CL-00000015","Dial","SIP/CL/61436523277,45","2011-08-26 14:47:06","2011-08-26 14:47:15","2011-08-26 ';
    $pattern = '/SIP\/CL\/([0-9]+),([0-9]+)/';
    $replacement = 'SIP/CL/\1|\2';
    $string = preg_replace($pattern, $replacement, $string);
    print($string);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2018-08-03
      相关资源
      最近更新 更多