使用多个分隔符拆分字符串

3

我看到了很多关于如何做到这一点的文章(在你标记这个问题为重复之前),但不知何故我的输出没有起作用:

// $delimiters wanted: ', ' | '; ' | ',' | ';' | ' , ' | ', and ' | ' and ' | ',and '
$str = 'Name 1, Name 2; Name 3;Name4 , Name 5,Name 6, and Name 7,and Name 8 and Name 9';
$delimiter = array(
    ', ',
    '; ',
    ';',
    ',',
    ' , ',
    ', and ',
    ' and ',
    ',and '
);
$str_new = explode( $delimiter[0], str_replace($delimiter, $delimiter[0], $str) );

然而,当我输出该数组时,我得到了这个结果:
<?php foreach($str_new as $new) { echo 'a' . $new; } ?>

Array (
    [0] => Name 1
    [1] => Name 2
    [2] => Name 3
    [3] =>        // WHY IS THIS EMPTY?
    [4] => Name 4
    ...
)

那么,有没有更好的方法来匹配我列出的分隔符呢?

名字4的空格放错地方了!你能把它改成名字 4 而不是 name4 吗? - caramba
@caramba,我想展示一下还有逗号前后有空格的情况。 - markb
4个回答

5
我会在您的情况下使用如下正则表达式:

我会在您的情况下使用如下正则表达式:

preg_split('/,? ?and | ?[,;] ?/', $str)

如果其他空格字符出现(例如TAB),您可能还希望将空格替换为\s,甚至可以使用\s*而不是?来覆盖多个空格的情况。


这个可以工作!但与“explode”相比,它有多么密集?需要超过100才能看到影响吗?实际上,我在字符串中只有不到20个。 - markb
@Ahhhhhhhhhhhhhdfgbv 我不知道确切的数值,但使用正则表达式的函数通常比简单字符串函数慢。因此,在大多数情况下,“explode”应该比“preg_split”快(我感觉大约快5倍)。但在我们的情况下,“explode”方法被内部替换(“preg_replace”或“str_replace”)减速了。 - Aleksei Zyrianov
看起来你比其他人多得到了3个赞。这也是有效的,并且只用了一行代码。此外,你甚至还加入了TAB,做得非常好。 - markb
谢谢。我已经比较了两种方法的速度。“explode”/“str_replace”在我的电脑上只比“preg_split”快1.6倍。 - Aleksei Zyrianov

1
你尝试过从php.net类似这样的东西吗?
<?php

//$delimiters has to be array
//$string has to be array

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);
?>

或者类似这样的 在PHP中使用多个分隔符拆分字符串


我已经尝试过这个,但是添加“,和”和“和”似乎会搞砸事情。 - markb

0

在你的代码中,Name 6Name 7之间,首先替换,,然后是and

因此,你最终得到这个字符串:

Name 1,Name 2,Name 3,Name4,Name 5,Name 6,,Name 7,Name 8,Name 9

因此,出现了空值...

在输出结果数组之前清理一下,你就可以了:

$str_out = array_filter($str_new);

0
你的方法存在问题,因为你试图用错误的方式解决问题。即使你设法创建了一个分隔符列表,如果你需要使用另一个字符(比如说'$'符号)来分隔单词,会发生什么?
你应该实现一个分词器/词法分析器,逐个字符读取输入并区分空格、终止符和非终止符号/字符。然后,词法分析器将生成一系列标记,例如:
STRING-SYMBOL:'NAME1' 
KOMMA-SYMBOL 
AND-SYMBOL 
STRING-SYMBOL:'NAME2' 
SEMICOLON-SYMBOL 
STRING-SYMBOL:'NAME3' 
AND-SYMBOL
...
EOF-SYMBOL

然后,您只需过滤掉任何非STRING-SYMBOL符号(或使用AND-SYMBOL组合字符串)。这是(在我看来)唯一坚如磐石的解决方案。它也非常容易扩展和推广:一旦您编写了一个不错的标记化程序/词法分析器,您就可以将此方法用于几乎任何字符串分析问题。

编写标记化程序通常非常简单:它逐个字符扫描输入,并首先对字符进行分类。它实现了一个简单的状态机来收集将形成符号的字符。

您可以尝试使用正则表达式来实现这一点,这也应该是可能的。无论如何,标记化程序将生成令牌列表(或在请求时检索下一个令牌)。它将检索的最后一个令牌是EOF-TOKEN,表示已完全遍历输入序列。


为什么这个回答完全忽略了问题的示例数据/上下文? - mickmackusa
你为什么认为这个答案“完全忽略了问题的示例数据/上下文”?它描述了如何为问题的示例数据定义的语言实现一个分词器。也许你不理解我9年前所指的内容。 - alzaimar
$str = 'Name 1, Name 2; Name 3;Name4 , Name 5,Name 6, and Name 7,and Name 8 and Name 9'; 这个答案在近十年里没有被任何人标记为有用,这并不奇怪。它是一个理论/学术文章,实际上并没有展示如何编写解决方法。您可能希望[编辑]您的帖子,使其对研究人员更有帮助。 - mickmackusa

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