PHP正则表达式组捕获

18

我有以下正则表达式:

\[([^ -\]]+)( - ([^ -\]]+))+\]

这个成功地匹配了下面的内容:

[abc - def - ghi - jkl]

但是匹配结果是:

Array
(
    [0] => [abc - def - ghi - jkl]
    [1] => abc
    [2] =>  - jkl
    [3] => jkl
)

我需要的是像这样的东西:

Array
(
    [0] => [abc - def - ghi - jkl]
    [1] => abc
    [2] =>  - def
    [3] => def
    [4] =>  - ghi
    [5] => ghi
    [6] =>  - jkl
    [7] => jkl
)

我能够在 C# 中通过查看“captures”组来做到这一点。如何在 PHP 中实现相同的功能?


5
你意识到字符类中的连字符 - 表示一个范围,而你的表达式 ' -\]' 意味着匹配从 \x20\x5D 中的任何字符。因此,[^ -\]][^ !"#$%&'()*+,\-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\]] 相同。你需要转义连字符 - - ridgerunner
你能展示一下在C#中用于此任务的正则表达式语法吗?从浏览文档来看,该语法与PHP使用的PCRE引擎的语法几乎完全相同。如果你遇到了问题,分析差异会很有趣。 - Charles
4个回答

19

这不是正则表达式应该处理的任务。匹配 \[([^\]]*)\],然后将第一个捕获结果使用 " - " 分隔符进行 explode

<?php                                                                       
  $str = "[abc - def - ghi - jkl]";
  preg_match('/\[([^\]]*)\]/', $str, $re);
  $strs = explode(' - ', $re[1]);
  print_r($strs);
?>

1
是的,你说得对,我不确定为什么我把事情弄得这么复杂。但我还是想知道是否可以像C#一样在PHP中完成这个功能(其中有“组捕获”)。 - carlosdubusm
1
警告:此函数在PHP 5.3.0中已被弃用,并在PHP 7.0.0中删除。链接。替代此函数的方法包括:preg_split(),explode(),str_split()。 - Cem Firat

12
假设您的示例字符串中的令牌不包含空格,且为字母数字符号:
<?php
    $pattern = "/([\w|\d])+/";
    $string = "[abc - 123 - def - 456 - ghi - 789 - jkl]";
    preg_match_all($pattern, $string, $matches);
    print_r($matches[0]);
?>

输出:

Array
(
    [0] => abc
    [1] => 123
    [2] => def
    [3] => 456
    [4] => ghi
    [5] => 789
    [6] => jkl
)

是的,这个也可以,谢谢。但我想在像这样的字符串上进行匹配和替换 "[a - b - c] [a] [a - b - f]"。所以[a]不会被替换,但其他的会被替换。我用preg_replace_callback解决了这个问题。无论如何还是谢谢! - carlosdubusm
3
@carlosdubusm:你应该编辑你的问题,包括你实际匹配的字符串。否则,你得到的答案可能对你没有用。 :) - drudge

9

SPL preg_match_all函数将返回从$matches变量的索引1开始的正则表达式组。例如,如果您想获取第二组,则可以使用$matches[2]

语法:

$matches = array(); 
preg_match_all(\
    '/(He)\w+ (\w+)/', 
    "Hello world\n Hello Sunshine", 
    $matches
); 
var_dump($matches);

结果:

array(3) {
  [0] =>
  array(2) {
    [0] =>
    string(11) "Hello world"
    [1] =>
    string(14) "Hello Sunshine"
  }
  [1] =>
  array(2) {
    [0] =>
    string(2) "He"
    [1] =>
    string(2) "He"
  }
  [2] =>
  array(2) {
    [0] =>
    string(5) "world"
    [1] =>
    string(8) "Sunshine"
  }
}

附言:我通过谷歌搜索被引导到这里,发布这个回答是为了回应问题标题的背景。这是我在搜索这个主题时感兴趣的信息。



6

为了将您的匹配项分组,请使用括号。例如:

$string = 'bob';
preg_match('/bob/', $string, $matches);

$matches的值将是['bob']

preg_match('/(b)(o)(b)/', $string, $matches);

$matches将是['bob','b','o','b']


1
你的 $matches 实际上将会是 ['bob', 'b', 'o', 'b'] - SparK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接