正则表达式:如何从匹配中排除字符?

时间:2011-07-28 14:34:06

标签: regex

我正在尝试解析以下字符串,类似于google对待搜索运算符的方式:

type1:words in key1 type2:word in key2 type3:key3

将组生成为键值对,例如

type1 -> words in key1 
type2 -> word in key2 
type3 -> key3

这是我到目前为止所得到的,但是比赛的结尾与下一对重叠,所以我只得到了第一组。

([\w\^]+):(.*?) \w+: 

type1 -> words in key1 

我觉得这应该通过反向引用来完成,但到目前为止我的尝试都失败了。什么是正确的方法?

4 个答案:

答案 0 :(得分:3)

(\w+):([^:]*)(?=\s\w|$)

适用于所有样本数据。

(\w+)    # Match a keyword
:        # Match :
([^:]*)  # Match as many non-colon characters as possible
(?=      # Lookahead assertion: backtrack to
 \s      # the closest space
|        # or
 $       # don't backtrack at all if we're at the end of the string
)        # End of lookahead

示例Python程序:

>>> import re
>>> r = re.compile(r"(\w+):([^:]*)(?=\s|$)")
>>> test = "type1:words in key1 type2:word in key2 type3:key3 type4:yet another key"
>>> for match in r.finditer(test):
...     print("{} -> {}".format(match.group(1), match.group(2)))
...
type1 -> words in key1
type2 -> word in key2
type3 -> key3
type4 -> yet another key

答案 1 :(得分:1)

为避免吃下一部分的开头,请使正则表达式的最后\w+:部分不消耗。这称为前瞻:

  

(?= re)通过零宽度正向前瞻(不消耗它)来匹配re。

所以你的正则表达式看起来像

([\w\^]+):(.*?) (?=\w+:|$)

答案 2 :(得分:0)

在模式上分割输入可能更容易

\s(?=\w+:\w)

或者,虽然它会颠倒匹配的顺序,但您可以从右到左进行评估并匹配

\w+:\w.*?

答案 3 :(得分:0)

我在php中的尝试:

preg_match_all( '/([\w\^]+?):(.+?)\s?(?=\w+:|$)/', 'type1:words in key1 type2:word in key2 type3:key3', $matches );
var_dump( $matches );

结果:

array(3) {
  [0]=>
  array(3) {
    [0]=>
    string(20) "type1:words in key1 "
    [1]=>
    string(19) "type2:word in key2 "
    [2]=>
    string(10) "type3:key3"
  }
  [1]=>
  array(3) {
    [0]=>
    string(5) "type1"
    [1]=>
    string(5) "type2"
    [2]=>
    string(5) "type3"
  }
  [2]=>
  array(3) {
    [0]=>
    string(13) "words in key1"
    [1]=>
    string(12) "word in key2"
    [2]=>
    string(4) "key3"
  }
}