的确,网络上存在很多这样的内容了,但今天我是来补充内容的,滑稽

众所周知,JS 中正则表达式 () 可以来获取匹配到内容,然后用 $0... 来显示。

嗯,都是正则,功能都是有的,但是直接的 $0 是没有的 --
很明显,这种形式正好戳中 PHP 变量的命名要求 - - $ + 变量命名要求(我觉得人人都知道,不打了不打了)

(pattern)

// 这个例子直接复制网上的,这里注释说明
$regex = '/(ab(c)+)+d(e)?/';
$str = 'abccde';
if(preg_match($regex, $str, $matches)){
   print_r($matches);
}
// 结果是
Array ( [0] => abccde [1] => abcc [2] => c [3] => e )

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

  • $pattern: 要搜索的模式,字符串形式。
  • $subject: 输入字符串。
  • $matches: 如果提供了参数 matches,它将被填充为搜索结果。$matches[0] 将包含完整模式匹配到的文本,$matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。
  • $flags:flags 可以被设置为以下标记值:
    • PREG_OFFSET_CAPTURE: 如果传递了这个标记,对于每一个出现的匹配返回时会附加字符串偏移量(相对于目标字符串的)。注意:这会改变填充到 matches 参数的数组,使其每个元素成为一个由第 0 个元素是匹配到的字符串,第 1 个元素是该匹配字符串在目标字符串 subject 中的偏移量。
  • offset: 通常,搜索从目标字符串的开始位置开始。可选参数 offset 用于指定从目标字符串的某个未知开始搜索(单位是字节)。

$flagsoffset 不经常用到,我是不想看 --

因此,获取正则的组,用 `preg_match` 的第三个参数,就可以轻松获取,以数组形式,0 是匹配到的内容,从 1 开始才是组 #

**但是,有问题出来肯定是在写项目中发现,我需要的是替换——** #

首先第一个思路,就是把 preg_match 匹配到的内容拿来搞事情,但是这样无疑是增加无用代码的数量。
因此,我将矛头指向:

preg_replace()

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

  • $pattern: 要搜索的模式,可以是字符串或一个字符串数组。
  • $replacement: 用于替换的字符串或字符串数组。
  • $subject: 要搜索替换的目标字符串或字符串数组。
  • $limit: 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。默认是 -1(无限制)。
  • $count: 可选,为替换执行的次数。

我们需要这么使用:

// 复制菜鸟教程
$string = 'google 123, 456';
$pattern = '/(\w+) (\d+), (\d+)/i';
$replacement = 'runoob ${2},$3';
echo preg_replace($pattern, $replacement, $string);

因为你想获取到组的内容,自然要在替换的地方使用组,${2}$3 都行,这就跟 JS 差不多了吧——
好了,今天就写到这了..

关于组的别名 (?P<name>pattern),非捕获组 (?:pattern),可以百度继续观看。

比如推荐

`\num` #

\num 是一个整数,是对捕获组的反向引用。 例如 \2 表示第二个子组匹配值,\1 表示第一个子组匹配值。

$regex = '/(\w)(\w)\2\1/';
$str = 'abba';

这意思 \2 代表第二个 (\w),形成这样对称的匹配。

`\k` #

了解了 (?P<name>pattern)\num,这个就不难理解了。\k<name> 是对命名捕获组的反向引用。其中 name 是捕获组名。

$regex = '/(?P<name>\w)abc\k<name>/';
$str = "fabcf";

于是这个就对应了 f……f

另外,预查的四种形式是零宽度的,匹配的时候只做一个判断,本身是不占位置的。/HE(?=L)LLO/HELLO 匹配,而 /HE(?=L)LO/HELLO 是不匹配的。毕竟但从字节数上两者就是不匹配的,前者只有 4 个,而后者有 5 个。

预查分为正向预查与反向预查。根据字面理解,正向预查是判断匹配字符串后面某些字符存在与否,而反向预查则是判断匹配字符串前面某些字符存在与否。

  • 正向预查判断存在使用 (?=pattern),判断不存在使用 (?!pattern)
  • 反向预查判断存在使用 (?<=pattern),判断不存在使用 (?<!pattern)