找到可选令牌之间的匹配?

时间:2012-11-21 23:56:47

标签: regex perl

对于字符串:

  • text::handle:e@ma.il::text
  • text::chat_identifier:chat0123456789&text

我有当前的正则表达式:

m/(handle:|chat_identifier:)(.+?)(:{2}|&)/

我目前正在使用$2来获取我想要的值(在第一个字符串e@ma.il中,在第二个字符串chat0123456789中)。

是否有更好/更快/更简单的方法来解决这个问题?

4 个答案:

答案 0 :(得分:4)

它是否“更好”取决于上下文,但您可以采用这种方法:将字符串拆分为“:”并获取结果列表的第四个元素。如果第三个字段可以是“handle”或“chat_identifier”以外的其他字段,则可以说比正则表达式更具可读性,更强大。

我认为这两种方法的速度都非常相似,但几乎可以用于perl中的任何实现。我想表明速度对于这个步骤至关重要,然后再担心它......

答案 1 :(得分:2)

对于正则表达式解决方案,这个解决方案稍微简单,不需要回溯:

m/(handle|chat_identifier):([^:&]+)/

注意略有不同:你的允许单个冒号在值内,我的不允许(它在遇到的第一个冒号时停止)。如果这不是问题,您可以使用我的变体。或者正如我在评论中提到的那样,在:处拆分并使用结果中的第四个元素。

只停留在双冒号的等效版本是:

m/(handle|chat_identifier):((?:(?!::|&).)+)/

不是那么漂亮,但它仍然避免回溯(前瞻可能会让它变慢,但是......如果速度很重要,你需要对其进行分析。)

答案 2 :(得分:1)

看起来你已经有了很多好的解决方案。拆分方法看起来最简单。但是根据您的要求,您还可以使用更通用的正则表达式来打破其基本部分中的字符串。它适用于其他数据类型和属性名称,而不是示例。

 ([^:]+)::([^:]+):([^:&]+)(?:::|&)\1

捕获组如下:

  • 第1组:数据类型。 (示例中的关键字“text”。)
  • 第2组:属性名称。 (关键字“handle”和“chat_identifier” 从你的例子。)
  • 第3组:财产价值。

答案 3 :(得分:1)

如果您想要的值始终位于同一位置,并且可以安全地拆分:&,那么以下内容可能适用于您:

use Modern::Perl;

say +( split /[:&]+/ )[2] for <DATA>;

__DATA__
text::handle:e@ma.il::text
text::chat_identifier:chat0123456789&text

输出:

e@ma.il
chat0123456789