5

我有一堆这样的字符串:

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,紧随其后的字符以及在下一个字符 + 主题标签之前的主题标签之后的所有内容都被捕获。

我有以下内容,只有当我在每个部分的末尾都有一个值时才能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
)

我看过这个问题和这个问题,它们相似,但没有一个对我有用。

所以,我的问题是为什么它只有在它后面跟着一个数字时才有效?以及我该如何解决?

在这里,您可以看到我拥有的一些示例字符串:

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

PS 字符串不区分大小写。

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

为什么不使用爆炸?

如果您查看我的示例,您会发现我还需要在 # 之前捕获字符。如果您认为有可能,explode()请同时发布输出,谢谢!

更新

我们是否应该关注为什么/([A-Z])+#/只有在包含数字时才有效?谢谢。

4

4 回答 4

6

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

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

  2. 如果后面紧跟一个字符#

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

演示

此表达式使用两个前瞻断言。结果在$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
)
于 2013-05-16T07:20:57.770 回答
4

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

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

从那时起,您之前只匹配主题标签和一个字母字符,而不是全部匹配。

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

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

于 2013-05-16T07:28:36.547 回答
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];

编辑:我更新了我的答案以反映更好地阅读问题

于 2013-05-16T07:15:21.000 回答
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);.

于 2013-05-16T07:21:50.463 回答