一个忽略引号内字符的 explode() 函数?

An explode() function that ignores characters inside quotes?

提问人:Pekka 提问时间:7/16/2010 更新时间:12/7/2012 访问量:6854

问:

有没有人知道一个快速简便的类似函数,可以忽略包含在一对任意字符(例如引号)中的拆分字符?explode()

例:

my_explode(
  "/", 
  "This is/a string/that should be/exploded.//But 'not/here',/and 'not/here'"
);

应生成一个具有以下成员的数组:

This is
a string 
that should be 
exploded.

But 'not/here', 
and 'not/here'

字符用单引号括起来的事实将使它们免于成为拆分器。

可以处理两个包装字符的解决方案的奖励积分

(not/here)

原生PHP解决方案是首选,但我认为不存在这样的事情!

PHP 字符串

评论

0赞 Bergi 9/11/2013
PHP 的可能副本会分解字符串,但将引号中的单词视为单个单词

答:

8赞 Ignacio Vazquez-Abrams 7/16/2010 #1

str_getcsv($str, '/')

链接页面上有一个 <5.3 的配方。

评论

0赞 Ignacio Vazquez-Abrams 7/16/2010
因此,然后传递一个不同的字符作为外壳。
0赞 Gordon 7/16/2010
无所谓。它返回Array ( [0] => This is [1] => a string [2] => that should be [3] => exploded. [4] => [5] => But 'not [6] => here', [7] => and 'not [8] => here' )
0赞 Ignacio Vazquez-Abrams 7/16/2010
对我来说,这闻起来像一个PHP错误。
1赞 Brilliand 12/7/2012
str_getcsv仅确认出现在拆分部分开头(即字符串开头或分隔符之后)的外壳字符。不是错误(它可以正确处理 CSV),但对这个问题没有好处。
1赞 kanchan 7/26/2016
str_getcsv($str,'/',“'”);第三个参数是外壳。
0赞 greg0ire 7/16/2010 #2

与preg_split非常接近的东西:https://www.php.net/manual/en/function.preg-split.php#92632

它处理多个包装字符和多个分隔符。

评论

0赞 Pekka 7/17/2010
干杯@greg0ire,这看起来不错,但仍需要一些工作。我将尝试用我对正则表达式的薄弱知识来改变它以满足我的需要。
5赞 Brilliand 12/7/2012 #3

这几乎是不可能的,因为你无法从字符串的中间判断你是否在引号之间。但是,可以完成这项工作。preg_splitpreg_match_all

单一报价的简单解决方案:

function quoted_explode($subject, $delimiter = ',', $quote = '\'') {
    $regex = "(?:[^$delimiter$quote]|[$quote][^$quote]*[$quote])+";
    preg_match_all('/'.str_replace('/', '\\/', $regex).'/', $subject, $matches);
    return $matches[0];
}

如果你给它传递某些特殊字符(\^-,根据 http://www.regular-expressions.info/reference.html),该函数将会出现各种问题,所以你需要转义这些字符。下面是一个常规解决方案,它转义了特殊的正则表达式字符,可以分别跟踪多种引号:

function regex_escape($subject) {
    return str_replace(array('\\', '^', '-', ']'), array('\\\\', '\\^', '\\-', '\\]'), $subject);
}

function quoted_explode($subject, $delimiters = ',', $quotes = '\'') {
    $clauses[] = '[^'.regex_escape($delimiters.$quotes).']';
    foreach(str_split($quotes) as $quote) {
        $quote = regex_escape($quote);
        $clauses[] = "[$quote][^$quote]*[$quote]";
    }
    $regex = '(?:'.implode('|', $clauses).')+';
    preg_match_all('/'.str_replace('/', '\\/', $regex).'/', $subject, $matches);
    return $matches[0];
}

(请注意,我将所有变量都保留在方括号之间,以尽量减少需要转义的内容 - 在方括号之外,特殊字符的数量大约是方括号的两倍。

如果你想用 ] 作为引号,那么你可能想用 [ 作为相应的引号,但我会把添加该功能作为读者的练习。 :)

评论

0赞 Brilliand 12/7/2012
边缘情况:如果引号不平衡,此函数将丢弃足够多的引号以使其平衡。
0赞 Brilliand 1/14/2014
我刚刚发现了这个函数 - 这可能是在正则表达式中转义字符的更好方法。preg_quote