【问题标题】:RegEx for hashtag separated string用于标签分隔字符串的正则表达式
【发布时间】:2013-05-16 16:24:10
【问题描述】:

我有一堆这样的字符串:

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
)

我也看过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

附:字符串不区分大小写。

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

为什么不使用爆炸?

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

更新

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

【问题讨论】:

  • @senk 我还需要在 # 之前捕获字符。
  • 您可以explode() 并从前一个数组项中复制最后一个字符。
  • @Voitcus 您可以尝试一下并将其作为答案发布吗?我仍然不知道你想如何用爆炸来捕捉那个角色。谢谢。
  • 这很混乱,你能不能设置不同的分隔符,你能不能把字符串变成这样:"a#aax1aay222,b#bbx4bby555bbz6,c#mmm1,d#ara1,e#abc"
  • @nacholibre 当然,我可以通过一些技巧来做到这一点;找到#,在-2 位置放一个,,但老实说我不喜欢那样做......

标签: php regex


【解决方案1】:

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

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

  2. 如果后面紧跟#,则为字符。

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

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
)

【讨论】:

  • 完美! ... 非常感谢您的帮助!你知道我的正则表达式出了什么问题吗?
  • Jack,顺便说一句,我选择 Marcus 答案作为接受,因为这解决了我在问题中提出的确切问题,但再次感谢您的回答!跨度>
  • @Mahdi 在大多数情况下,preg_split() 可以改为preg_match_all();在我自己看来,它更容易遵循逻辑,即使 preg_split() 在这里实际上是可能的。
  • 你是对的,但我的意思是因为Marcus 正在修复我的正则表达式,而且看起来更简单,我选择了他的答案作为接受。我认为他的解决方案也更有效。我仍然喜欢你构建正则表达式的方式,但我相信如果我选择他的解决方案会更公平。
  • @Mahdi 效率应该永远是最后一件事,但马库斯的回答非常好:)
【解决方案2】:

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

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

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

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

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

【讨论】:

  • 哇,效果很好……也感谢您的解释!
  • @Mahdi 您可能希望使用 A-Za-z0-9 让小写/大写一起工作(如您的示例),如果您想使用数字(如您的更新)
  • @Marcus 更新您的答案,以便答案的代码与链接的代码匹配
【解决方案3】:

使用explode() 而不是正则表达式

$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];

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

【讨论】:

  • 目标是在自己的数组元素中捕获#之前的字符;重读问题。
  • @nl-x 好吧,正如我上面提到的,我试图避免在我的项目中编写棘手的代码。但感谢您的努力。 :)
  • @nl-x +1 因为你的努力 :)
【解决方案4】:

您可以使用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,-1);,而不是substr($item,0,strlen($item)-1);

【讨论】:

  • @Jack 也许你需要连接最后一部分。当explode 返回单个字符时,这也会插入空字符串,也许它们应该被删除。
  • 感谢您的努力......但你知道,最近我试图避免编程中的技巧,我相信每个问题总有[至少]一个适当的解决方案。也请查看Jack 答案:)
  • @Voitcus 无论如何感谢您的努力 :)
猜你喜欢
  • 2017-01-18
  • 2014-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-02
  • 2011-09-25
相关资源
最近更新 更多