RegEx用于hashtag分隔的字符串

时间:2013-05-16 07:05:52

标签: php regex

我有很多这样的字符串:

a#aax1aay222b#bbx4bby555bbz6c#mmm1d#ara1e#abc

我需要做的是根据hashtag位置将它们拆分成这样的东西:

Array
(
    [0] => A
    [1] => AAX1AAY222
    [2] => B
    [3] => BBX4BBY555BBZ6
    [4] => C
    [5] => MMM1
    [6] => D
    [7] => ARA1
    [8] => E
    [9] => ABC
)

所以,正如您所看到的那样,hashtag后面的角色被捕获,而且正好在下一个char + hashtag之前的hashtag后面的所有内容。

我有以下RegEx,当我在每个部分的末尾都有numeric值时,它只能

以下是RegEx设置:

preg_split('/([A-Z])+#/', $text, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);

它可以正常使用这样的东西:

C#mmm1D#ara1

但是,如果我将其改为此(删除数字):

C#mmmD#ara

那将是结果,这是不好的:

    Array
(
    [0] => C
    [1] => D
)

我已经查看了this个问题和this一个问题,这些问题类似,但没有一个对我有用。

所以,我的问题是为什么它只有跟着一个数字才能起作用?以及我如何解决它?

在这里你可以看到我们的一些示例字符串:

a#123b#abcc#def456         // A:123, B:ABC, C:DEF456
a#abc1def2efg3b#abcdefc#8  // A:ABC1DEF2EFG3, B:ABCDEF, C:8
a#abcdef123b#5c#xyz789     // A:ABCDEF123, B:5, C:XYZ789

P.S。字符串不区分大小写。

P.P.S。如果您曾经想过这些字符串到底是什么,它们是用户提交的调查问卷的答案,我不能对它们做任何事情,比如重构,因为它们已经存储并且只需要继续。

为什么不使用爆炸?

如果你看一下我的例子,你会发现我需要在#之前捕捉角色。如果您认为explode()可以发布,请发布输出,谢谢!

更新

我们是否应该关注为什么/([A-Z])+#/仅在包含数字的情况下有效?感谢。

4 个答案:

答案 0 :(得分:6)

而不是使用preg_split(),而是决定要匹配的内容:

  1. 如果<any-char>#<end-of-string>后跟一组“字词”。

  2. 如果紧跟#后的字符。

    $str = 'a#aax1aay222b#bbx4bby555bbz6c#mmm1d#ara1e#abc';
    
    preg_match_all('/\w+(?=.#|$)|\w(?=#)/', $str, $matches);
    
  3. Demo

    此表达式使用两个前瞻断言。结果位于$matches[0]

    <强>更新

    另一种看待它的方式是:

    preg_match_all('/(\w)#(\w+)(?=\w#|$)/', $str, $matches);
    
    print_r(array_combine($matches[1], $matches[2]));
    

    每个条目以单个字符开头,后跟哈希,后跟X个字符,直到遇到字符串的结尾或下一个条目的开头。

    输出是这样的:

    Array
    (
        [a] => aax1aay222
        [b] => bbx4bby555bbz6
        [c] => mmm1
        [d] => ara1
        [e] => abc
    )
    

答案 1 :(得分:4)

如果您仍想使用preg_split,可以删除+,它可能会按预期工作:

'/([A-Z])#/i'

从那时起,您只匹配主题标签和一个字母字符,而不是所有字符。

示例:http://codepad.viper-7.com/z1kFDb

编辑:在模式中添加了不区分大小写的标记i

答案 2 :(得分:1)

使用explode()而不是Regexp

$tmpArray = explode("#","a#aax1aay222b#bbx4bby555bbz6c#mmm1d#ara1e#abc");
$myArray = array();
for($i = 0; $i < count($tmpArray) - 1; $i++) {
    if (substr($tmpArray[$i],0,-1)) $myArray[] = substr($tmpArray[$i],0,-1);
    if (substr($tmpArray[$i],-1)) $myArray[] = substr($tmpArray[$i],-1);
}
if (count($tmpArray) && $tmpArray[count($tmpArray) - 1]) $myArray[] = $tmpArray[count($tmpArray) - 1];

编辑:我更新了我的回答,以便更好地阅读问题

答案 3 :(得分:0)

您可以使用explode()函数来分割除了哈希符号之外的字符串,如之前给出的答案中所述。

$myArray = explode("#",$string);

对于字符串'a#aax1aay222b #bbx4bby555bbz6c #mmm1d#ara1e#abc',这将返回类似

的内容
$myarray = array('a', 'aax1aay22b', 'bbx4bby555bbz6c' ....);

现在您只需要将数组中每个字符串的最后一个字符作为另一个项目。

$copy = array();
foreach($myArray as $item){
  $beginning = substr($item,0,strlen($item)-1); // this takes all characters except the last one
  $ending = substr($item,-1); // this takes the last one
  $copy[] = $beginning;
  $copy[] = $ending;
} // end foreach

这是一个例子,没有经过测试。

修改

而不是substr($item,0,strlen($item)-1);,您可以使用substr($item,0,-1);