首页 > 解决方案 > 正则表达式模式而不是爆炸

问题描述

我有这样的文字:

NodeName: 
 nd1,
 nd2
 
 ;
 
SqlData: 

{code:java}
   select id, regexp_replace(username, '[;]+'::text, ','::text, 'g'::text) from users where id =1
{code}

    {code:java}
   select username from users where id =1
{code}
;

SqlFiles:

{code:java}
   select filename || ';'::text from users where id =1
{code}
;

哪里可以是新行,行之间的空格等。我想用';'分隔这个字符串 符号以获取以下字符串(没有结束行和空格):

NodeName:nd1,nd2 
------ 
SqlData:{code:java}select id, regexp_replace(username, '[;]+'::text, ','::text, 'g'::text) from users where id =1{code}{code:java}select username from users where id =1{code}
------
SqlFiles:{code:java}select filename || ';'::text from users where id =1{code}

我不能简单地使用explode这样的功能:

$res = explode(';', $str);

因为';'可以在代码标签里面的SQL查询中使用。

所以我看到的唯一方法是使用preg_match_all一些模式。

我用

preg_match_all('\(?s)(?<=\{code:java\}).*?(?=\{code\})|.*?;\', $str, $res);

但它仍然返回 5 个匹配而不是 3 个。

任何想法如何纠正模式以使其工作?

标签: phpregex

解决方案


您可以使用更具体的模式来匹配不同的部分并删除换行符。

您可以使用负前瞻来排除以不允许的模式开头的匹配行,并防止匹配停止在{code:java}后面不跟;

^(?:NodeName:\h*(?:\R(?!\h*;$).*)*|Sql(?:Data|Files):\h*\R+{code:java}(?:\R(?!{code}\R\h*;$).*)*\R{code})(?=\R+\h*;$)
  • ^字符串的开始
  • (?:轮换的非捕获组|
    • NodeName:\h*匹配NodeName:和可选的水平空白字符
    • (?:\R(?!\h*;$).*)*重复匹配所有不以可选空格开头和;字符串末尾的行
    • |或者
    • Sql(?:Data|Files):\h*匹配SqlData:SqlFiles:以及可选空格
    • \R+{code:java}匹配换行符和{code:java}
    • (?:\R(?!{code}\R\h*;$).*)*重复匹配所有不以{code}开头的行,后跟换行符,并;在字符串的末尾
    • \R{code}匹配换行符和{code}
  • )关闭非捕获组
  • (?=\R+\h*;$)正向前瞻,断言 1+ 换行符,可选的 whitspace 字符和;右侧字符串的末尾

正则表达式演示| php演示

示例代码$str示例字符串在哪里。

$re = '/^(?:NodeName:\h*(?:\R(?!\h*;$).*)*|Sql(?:Data|Files):\h*\R+{code:java}(?:\R(?!{code}\R\h*;$).*)*\R{code})(?=\R+\h*;$)/m';
preg_match_all($re, $str, $matches);
$result = array_map(function($x){
    return preg_replace("/\R+/", "", $x);
}, $matches[0]);
print_r($result);

输出

Array
(
    [0] => NodeName:  nd1, nd2 
    [1] => SqlData: {code:java}   select id, regexp_replace(username, '[;]+'::text, ','::text, 'g'::text) from users where id =1{code}    {code:java}   select username from users where id =1{code}
    [2] => SqlFiles:{code:java}   select filename || ';'::text from users where id =1{code}
)

推荐阅读