在 PHP 中,如何使用多个分隔符进行字符串切割?

188

我有一个问题,我有一个字符串数组,我想用不同的分隔符进行拆分。例如:

$example = 'Appel @ Ratte';
$example2 = 'apple vs ratte'

我需要一个用 @ 或 vs 分割的数组。

我已经写了一个解决方案,但如果有更好的解决方案,请在这里发帖。

private function multiExplode($delimiters,$string) {
    $ary = explode($delimiters[0],$string);
    array_shift($delimiters);
    if($delimiters != NULL) {
        if(count($ary) <2)                      
            $ary = $this->multiExplode($delimiters, $string);
    }
    return  $ary;
}

我从来没有见过有人回答问题时用“这个如何”、“那个怎么样”之类的话。 - HosseyNJF
12个回答

349

尝试使用以下方法:

$output = preg_split('/ (@|vs) /', $input);

8
如果你希望使用复杂的字符串解析来构建一个大型系统,那么拥有自己的解析器是最有效的方式。否则,它对系统速度的影响不大,但是你更愿意使用对你来说最简单的方式(以达到节约成本的目的)。 - SergeS
13
请注意,有些字符需要转义才能正常工作(例如/?)。例如:preg_split("/(\/|\?|=)/", $foo); - kenorb
7
我发现在/()/之间放置空格会导致preg_split无法工作。我必须删除空格,然后它才能按预期工作(使用PHP 7)。 - Boardy
1
空格用于区分“vs”作为单独字符串和“vs”作为某些(可能奇怪的)单词的一部分-尝试使用\s替换空格。 - SergeS
1
@GuyGordon 如果您更改分隔子字符串,那么当然这个特定设计的模式将失败。为什么要发表这样的评论呢?也许如果这个答案真正解释了它是如何工作和做什么的话,人们会更容易地调整这个答案的建议以适应他们自己的项目。换句话说,在Stack Overflow上,仅有代码的答案价值较低,因为它们错过了教育/授权提问者和成千上万未来研究人员的机会。 - mickmackusa
显示剩余4条评论

85
您可以使用 str_replace 函数将第一个字符串中的所有 @ 替换为 vs,然后在 vs 上使用 explode,或者反过来。

1
简单的解决方案,最终用于Json代码中将“}}”替换为“|”。有点不太规范,但很有效! - Baldráni
当一个分隔符是另一个的超集时(例如 (@|@!) 情况),这将无法正常工作。 - user719662
2
@vaxquis 是的,它会。str_replace('@!', '@',$str); 确保您从最独特的分隔符开始。 - John Ballinger
@JohnBallinger 不,它不会 - 你提出了另一个解决方案,这清楚地表明原始解决方案不会正常工作,而你的想法是有缺陷的。想象一下,你不知道哪个是另一个的超集。你需要创建另一行代码来检查等等。虽然我总体上讨厌正则表达式,但在可维护性和简单性方面,这是最好的解决方案。 - user719662
2
@vaxquis - 虽然你提出了一个很好的观点,但需要注意的是,即使使用 preg_split(),在你提到的情况下仍然会存在问题。考虑一下 preg_split('/(@|@!)/','A@B@!C')preg_split('/(@!|@)/','A@B@!C') 的输出差异。分隔符的顺序改变了结果。只要你小心地排列分隔符数组,John 的解决方案就能够同样有效。 - But those new buttons though..

67
function multiexplode ($delimiters,$string) {

    $ready = str_replace($delimiters, $delimiters[0], $string);
    $launch = explode($delimiters[0], $ready);
    return  $launch;
}

$text = "here is a sample: this text, and this will be exploded. this also | this one too :)";


$exploded = multiexplode(array(",",".","|",":"),$text);

print_r($exploded);

//And output will be like this:
// Array
// (
//    [0] => here is a sample
//    [1] =>  this text
//    [2] =>  and this will be exploded
//    [3] =>  this also 
//    [4] =>  this one too 
//    [5] => )
// )

来源:php@metehanarslan at php.net


喜欢这个答案使用str_replace的方式。非常聪明和简洁的解决方案。 - Hybrid web dev

14

你可以尝试使用strtr()函数,将所有其他分隔符替换为第一个分隔符。

private function multiExplode($delimiters,$string) {
    return explode(
        $delimiters[0],
        strtr(
            $string,
            array_combine(
                array_slice(    $delimiters, 1  ),
                array_fill(
                    0,
                    count($delimiters)-1,
                    array_shift($delimiters)
                )
            )
        )
    );
}

我想它有点难读,但我在这边测试了一下它是可行的。

单行代码最棒啦!


12

2
由于他的定界符是“vs”,这可能不起作用,因为PHP文档指出:strtok()将字符串(str)分割成较小的字符串(token),每个标记都由任何来自token的字符定界。而“vs”包含两个字符。 - mikewasmike

10

你可以简单地使用以下代码:

$arr=explode('sep1',str_replace(array('sep2','sep3','sep4'),'sep1',$mystring));

这个回答没有尝试满足所问的问题。为什么你完全忽略了提问者提供的数据和所需的输出?我不明白为什么这个只有代码的答案得分如此之高。 - mickmackusa

6

你可以尝试这个解决方案,它非常有效。

它将所有分隔符替换为一个普通分隔符"chr(1)", 然后使用该分隔符将字符串拆分。

function explodeX( $delimiters, $string )
{
    return explode( chr( 1 ), str_replace( $delimiters, chr( 1 ), $string ) );
}
$list = 'Thing 1&Thing 2,Thing 3|Thing 4';

$exploded = explodeX( array('&', ',', '|' ), $list );

echo '<pre>';
print_r($exploded);
echo '</pre>';

来源: http://www.phpdevtips.com/2011/07/exploding-a-string-using-multiple-delimiters-using-php/

本文介绍了如何使用PHP在字符串中使用多个分隔符进行拆分。实现这一目标的最简单方法是使用preg_split函数。此外,该文章还提供了一个基于类的解决方案,可以使用多个不同种类的分隔符进行字符串拆分。通过阅读本文,您将了解到在PHP中如何灵活地处理文本数据。


现在这个解决方案很愚蠢,可能会返回错误的结果。 - Your Common Sense
1
你还有什么建议吗?如果你能告诉我问题出在哪里,那就太好了。 - Mayur Chauhan
求婚?我?难道这里不是已经有了最佳答案吗?简洁、清晰且没有错误? - Your Common Sense
1
同意,谢谢常识。 - Mayur Chauhan

2

我是这样做的...

public static function multiExplode($delims, $string, $special = '|||') {

    if (is_array($delims) == false) {
        $delims = array($delims);
    }

    if (empty($delims) == false) {
        foreach ($delims as $d) {
            $string = str_replace($d, $special, $string);
        }
    }

    return explode($special, $string);
}

$delims = array($delims); 可以无条件地调用,以确保变量是数组类型。 empty() 检查是完全不必要的,因为变量已经被声明,如果它是空的,那么 foreach 将不会被执行。多次调用 str_replace() 是不必要的,因为 str_replace() 的第一个参数可以轻松接收一个数组。在这个仅包含代码的答案中,我没有太多想保留的东西。请参见 @MayurChauhan 的改进版本。 - mickmackusa
更正:可以无条件地声明 $delims = (array)$delims; - mickmackusa
Nope: https://paste.pics/GD6BO https://paste.pics/GD6BU - Vaci
你为什么说“不行”?你没有展示你调整后的代码。 - mickmackusa
如此示例所示,您的代码片段过于复杂。 - mickmackusa

2
最初的回答是什么?
这个怎么样?
/**
 * Like explode with multiple delimiters. 
 * Default delimiters are: \ | / and ,
 *
 * @param string $string String that thould be converted to an array.
 * @param mixed $delimiters Every single char will be interpreted as an delimiter. If a delimiter with multiple chars is needed, use an Array.
 * @return array. If $string is empty OR not a string, return false
 */
public static function multiExplode($string, $delimiters = '\\|/,') 
{
  $delimiterArray = is_array($delimiters)?$delimiters:str_split($delimiters);
  $newRegex = implode('|', array_map (function($delimiter) {return preg_quote($delimiter, '/');}, $delimiterArray));
  return is_string($string) && !empty($string) ? array_map('trim', preg_split('/('.$newRegex.')/', $string, -1, PREG_SPLIT_NO_EMPTY)) : false;
}

在您的情况下,应该使用一个数组作为$delimiters参数。这样就可以将多个字符用作一个分隔符。
如果您不关心结果中的尾随空格,则可以在返回行中删除array_map('trim', [...] )部分。(但在这种情况下不要挑剔。保留preg_split。)
所需的PHP版本:5.3.0或更高版本。
您可以在这里进行测试。

1

你使用这种分隔方法可能会遇到一些问题(例如,如果你有这个字符串:“vs @ apples”),但是如果我们先声明你已经考虑过并解决了所有可能的冲突,那么你可以将所有出现的$delimiter [1]替换为$delimiter [n],然后在第一个上进行分割?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接