试图分割逗号分隔的字符串,忽略引号和括号

  • 本文关键字:分割 分隔 字符串 php regex
  • 更新时间 :
  • 英文 :


我试图将文本分成逗号分隔的组,除非逗号在双引号或单引号中,或在括号中。

  1. a,b=456应该找到ab=345
  2. a='123,456',b应该找到a='123,456'b
  3. a=x(1,2,3),b,c应该找到a=x(1,2,3)bc

我试过str_getcsv和一些preg_split,但我似乎不能得到正确的模式。

使用以下代码

function test($n, $a,$b) {
echo "Test $n";
if ( $a===$b ) echo "=<span style='color:green'>CORRECT ************************</span>";
else echo "=<span style='color:red'>WRONG</span>";
echo "<PRE>".print_r($b, true)."</PRE>";
echo "<HR>n";
}
$t=    'lorem ipsum=123,delor='1,456',sit="123,456",amet=xxx(2,3),"consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."';
$want=["lorem ipsum=123","delor='1,456'","sit="123,456"","amet=xxx(2,3)","consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."];

echo "WANTED.<PRE style='color:green'>".print_r($want, true)."</PRE><HR>";
//Array
//(
//    [0] => lorem ipsum=123
//    [1] => delor='1,456'
//    [2] => sit="123,456"
//    [3] => amet=xxx(2,3)
//    [4] => consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
//)

test("1 explode", $want, explode(",", $t));
// Test 1 explode=WRONG
// Array
// (
//     [0] => lorem ipsum=123
//     [1] => delor='1
//     [2] => 456'
//     [3] => sit="123
//     [4] => 456"
//     [5] => amet=xxx(2
//     [6] => 3)
//     [7] => "consectetur adipiscing elit
//     [8] =>  sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
// )

test("2 str_getcsv", $want, str_getcsv($t, ",", "'"));
// Test 2 str_getcsv=WRONG
// Array
// (
//     [0] => lorem ipsum=123
//     [1] => delor='1
//     [2] => 456'
//     [3] => sit="123
//     [4] => 456"
//     [5] => amet=xxx(2
//     [6] => 3)
//     [7] => "consectetur adipiscing elit
//     [8] =>  sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
// )

test("3 str_getcsv", $want, str_getcsv($t, ",", """));
// Test 2 str_getcsv=WRONG
// Array
// (
//     [0] => lorem ipsum=123
//     [1] => delor='1
//     [2] => 456'
//     [3] => sit="123
//     [4] => 456"
//     [5] => amet=xxx(2
//     [6] => 3)
//     [7] => "consectetur adipiscing elit
//     [8] =>  sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
// )    

test("4 preg_split", $want, preg_split("/,/", $t));
// Test 4 preg_split=WRONG
// Array
// (
//     [0] => lorem ipsum=123
//     [1] => delor='1
//     [2] => 456'
//     [3] => sit="123
//     [4] => 456"
//     [5] => amet=xxx(2
//     [6] => 3)
//     [7] => "consectetur adipiscing elit
//     [8] =>  sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
// )

我已经失去了大量的时间搜索和尝试不同的模式-我敢肯定我会写一个字符串解析器比这更快-但也许-有人能给我一个很好的模式,通过这个工作?

我在https://onlinephp.io/c/3f4d3上放了一个示例测试来运行这个代码

感谢

我建议使用

preg_match_all('~(?:'[^']*'|"[^"]*"|(((?:[^()]++|(?1))*))|[^'",])+~', $text, $matches)

或者,如果在加引号的子字符串中可以有转义序列:

preg_match_all('~(?:'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"|(((?:[^()]++|(?1))*))|[^'",])+~s', $text, $matches)

参见regex演示。

细节:

  • (?:-非捕获组的开始(在这里充当容器):
    • '[^'\\]*(?:\\.[^'\\]*)*'|-支持转义序列的单引号之间的字符串,或
    • "[^"\\]*(?:\\.[^"\\]*)*"|-支持转义序列的双引号之间的字符串,或
    • (((?:[^()]++|(?1))*))|-两个成对嵌套括号之间的字符串
    • [^'",]-',",以外的字符
  • )+-一个或多个序列。

最新更新