PHP preg_split() 模式

PHP preg_split() pattern

我需要帮助使用 preg_split() 找到 PCRE 模式。

我正在使用下面的正则表达式模式根据字符串的起始 3 个字符代码和分号拆分字符串。该模式在 Javascript 中运行良好,但现在我需要在 PHP 中使用该模式。我试过 preg_split() 但只是找回了垃圾。

// 每组将以三个字母代码开头,三个部分用分号分隔。字符串不会以分号结束。

// Pseudocode    
string_to_split = "AAA;RED;111;BBB;BLUE;22;CCC;GREEN;33;DDD;WHITE;44"

// This works in JS  
// https://regex101.com  
$pattern = "/[AAA|BBB|CCC|DDD][^;]*;[^;]*[;][^;]*/gi";

Match 1  
Full match  0-11    `AAA;RED;111`  
Match 2  
Full match  12-23   `BBB;BLUE;22`  
Match 3  
Full match  24-36   `CCC;GREEN;33`  
Match 4  
Full match  37-49   `DDD;WHITE;44`  

$pattern = "/[AAA|BBB|CCC|DDD][^;]*;[^;]*[;][^;]*/";  
$split = preg_split($pattern, $string_to_split);

returns

array(5)  
    0:""  
    1:";"  
    2:";"  
    3:";"  
    4:""  

我稍微修改了你的模式,并向 preg_split 添加了几个标志。

PREG_SPLIT_NO_EMPTY 标志将从结果中排除空匹配,PREG_SPLIT_DELIM_CAPTURE 将在结果中包含捕获的值。

$split = preg_split('/([abcd]{3};[^;]+;\d+);?/i', $string, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);

结果:

Array
(
    [0] => AAA;RED;111
    [1] => BBB;BLUE;22
    [2] => CCC;GREEN;33
    [3] => DDD;WHITE;44
)

或者,您可以将 preg_match_all 与以下模式一起使用,这样更合适。

preg_match_all('/([abcd]{3};[^;]+;\d+);?/i', $string, $matches);

print_r($matches[0]);

结果:

Array
(
    [0] => AAA;RED;111
    [1] => BBB;BLUE;22
    [2] => CCC;GREEN;33
    [3] => DDD;WHITE;44
)

根据您在对答案的一些评论中提供的附加信息,我更新了我的答案以使其非常适合您的源格式。

你可能想要这样的东西:

$subject = "AAA;RED;111;AAA;Oh my dog;12.34;AAA;Oh Long John;.4556;BBB;Oh Long Johnson;1.2323;BBB;Oh Don Piano;.33;CCC;Why I eyes ya;1.445;CCC;All the live long day;2.3343;DDD;Faith Hilling;.89";

$pattern = '/(?<=;|^)(AAA|BBB|CCC|DDD);([^;]*);((?:\d*\.)?\d+)(?=;|$)/';
preg_match_all($pattern, $subject,$matches);
var_dump($matches);

给你

array (size=4)
  0 =>
    array (size=8)
      0 => string 'AAA;RED;111' (length=11)
      1 => string 'AAA;Oh my dog;12.34' (length=19)
      2 => string 'AAA;Oh Long John;.4556' (length=22)
      3 => string 'BBB;Oh Long Johnson;1.2323' (length=26)
      4 => string 'BBB;Oh Don Piano;.33' (length=20)
      5 => string 'CCC;Why I eyes ya;1.445' (length=23)
      6 => string 'CCC;All the live long day;2.3343' (length=32)
      7 => string 'DDD;Faith Hilling;.89' (length=21)
  1 =>
    array (size=8)
      0 => string 'AAA' (length=3)
      1 => string 'AAA' (length=3)
      2 => string 'AAA' (length=3)
      3 => string 'BBB' (length=3)
      4 => string 'BBB' (length=3)
      5 => string 'CCC' (length=3)
      6 => string 'CCC' (length=3)
      7 => string 'DDD' (length=3)
  2 =>
    array (size=8)
      0 => string 'RED' (length=3)
      1 => string 'Oh my dog' (length=9)
      2 => string 'Oh Long John' (length=12)
      3 => string 'Oh Long Johnson' (length=15)
      4 => string 'Oh Don Piano' (length=12)
      5 => string 'Why I eyes ya' (length=13)
      6 => string 'All the live long day' (length=21)
      7 => string 'Faith Hilling' (length=13)
  3 =>
    array (size=8)
      0 => string '111' (length=3)
      1 => string '12.34' (length=5)
      2 => string '.4556' (length=5)
      3 => string '1.2323' (length=6)
      4 => string '.33' (length=3)
      5 => string '1.445' (length=5)
      6 => string '2.3343' (length=6)
      7 => string '.89' (length=3)

开始标记应出现在字符串的开头或紧跟在分号之后,因此我们进行后视,寻找开始或分号:

(?<=;|^)

我们寻找 AAA、BBB、CCC 或 DDD 的替代方案并捕获它:

(AAA|BBB|CCC|DDD)

在分号之后,我们寻找分号以外的任何字符。量词 * 表示 0 次或更多次。如果您至少需要 1 个,请使用 +

;([^;]*)

在下一个分号后查找数字。此任务必须拆分以适合有效格式:我们首先查找 0 个或更多数字后跟一个点:

(?:\d*\.)?

其中 (?:) 表示非捕获组。

后面我们至少找一个数字:\d+

我们想在搜索到的分号后使用括号捕获数字的两个部分:

;((?:\d*\.)?\d+)

这匹配“1234”、“.1234”、“1.234”、“12.34”、“123.4”,但“1234.”、“1.2.3”

最后,我们希望它立即出现在分号或字符串结尾之前。因此我们做一个前瞻:

(?=;|$)

先行和后行不属于之前或之后的捕获结果的一部分。

您不想拆分字符串而是匹配元素,请使用 preg_match_all:

$str = "AAA;RED;111;AAA;Oh my dog;2.34;AAA;Oh Long John;.4556;BBB;Oh Long Johnson;1.2323;BBB;Oh Don Piano;.33;CCC;Why I eyes ya;1.445;CCC;All the live long day;2.3343;DDD;Faith Hilling;.89";
$res = preg_match_all('/(?:AAA|BBB|CCC|DDD);[^;]*;[^;]*;?/', $str, $m);
print_r($m[0]);

输出:

Array
(
    [0] => AAA;RED;111;
    [1] => AAA;Oh my dog;2.34;
    [2] => AAA;Oh Long John;.4556;
    [3] => BBB;Oh Long Johnson;1.2323;
    [4] => BBB;Oh Don Piano;.33;
    [5] => CCC;Why I eyes ya;1.445;
    [6] => CCC;All the live long day;2.3343;
    [7] => DDD;Faith Hilling;.89
)

解释:

/                       : regex delimiter
  (?:AAA|BBB|CCC|DDD)   : non capture group AAA or BBB or CCC or DDD
  ;                     : a semicolon
  [^;]*                 : 0 or more any character that is not a semicolon
  ;                     : a semicolon
  [^;]*                 : 0 or more any character that is not a semicolon
  ;?                    : optional semicolon
/                       : regex delimiter