匹配不在bbcode标记内的正则表达式模式

时间:2018-01-10 05:34:06

标签: php regex

我正在尝试创建一个正则表达式,用于匹配以@开头的字符串中的单词

解决这个初始问题的正则表达式是'~(@\w+)~'

代码的第二个要求是它还必须忽略[quote][/quote]标记内发生的任何匹配

失败的几次尝试是:

(?:[0-9]+|~(@\w+)~)(?![0-9a-z]*\[\/[a-z]+\])

/[quote[\s\]][\s\S]*?\/quote](*SKIP)(*F)|~(@\w+)~/i

示例:以下字符串应具有显示的数组输出:

$results = [];
$string = "@friends @john [quote]@and @jane[/quote] @doe";

//run regex match
preg_match_all('regex', $string, $results);

//dump results
var_dump($results[1]);

//results: array consisting of:
    [1]=>"@friends"
    [2]=>"@john"
    [3]=>"@doe

1 个答案:

答案 0 :(得分:2)

您可以使用以下正则表达式(基于another related question):

'~(\[quote](?:(?1)|.)*?\[/quote])(*SKIP)(*F)|@\w+~s'

请参阅regex demo。正则表达式考虑了嵌套的[quote]标记。

<强>详情

  • (\[quote](?:(?1)|.)*?\[/quote])(*SKIP)(*F) - 匹配捕获括号内的模式,然后(*SKIP)(*F)使正则表达式引擎省略匹配的文本:
    • \[quote] - 文字[quote]字符串
    • (?:(?1)|.)*? - 整个第1组模式((?1))或任何字符(.
    • 的任何0+(但尽可能少)出现
    • \[/quote] - 文字[/quote]字符串
  • | - 或
  • @\w+ - @后跟1个字的字符。

PHP demo

$results = [];
$string = "@friends @john [quote]@and @jane[/quote] @doe";
$rx = '~(\[quote\](?:(?1)|.)*?\[/quote])(*SKIP)(*F)|@\w+~s';
preg_match_all($rx, $string, $results);
print_r($results[0]);
// => Array ( [0] => @friends [1] => @john [2] => @doe )