如何在任意索引处选择正则表达式匹配?

时间:2010-07-19 03:48:52

标签: regex

我有一个看起来像的字符串:

  

ABC-DEF01-GHI54677-JKL!9988-MNOP

每个-之间几乎可以重复任何次数的任何字符。

我正在使用这个正则表达式:

[^-]*

如何让它与第二个索引(例如DEF01)的匹配“匹配”?或第3(GHI54677)或第4(JKL!9988)?

我正在使用的引擎不允许我指定匹配索引或其他代码 - 它必须在表达式中完成。

3 个答案:

答案 0 :(得分:2)

第二组parens将分别捕获“DEF”,“GHI”和“JKL”......

([^-]+-){1}([^-]+)
([^-]+-){2}([^-]+)
([^-]+-){3}([^-]+)

如果这是perl,则使第一组parens不捕获,即:

# perl -de 0
$_="ABC-DEF-GHI-JKL-MNO"
p /(?:[^-]+-){1}([^-]+)/
  DEF
p /(?:[^-]+-){2}([^-]+)/
  GHI
p /(?:[^-]+-){3}([^-]+)/
  JKL

$_="ABC-DEF01-GHI54677-JKL!9988-MNOP"
p /(?:[^-]+-){1}([^-]+)/
  DEF01
p /(?:[^-]+-){2}([^-]+)/
  GHI54677
p /(?:[^-]+-){3}([^-]+)/
  JKL!9988

说明:

(?:  = non-capturing parens
[^-] = a non-dash character
+    = one or more
-    = a dash
)    = close paren
{3}  = repeat 3 times

这部分“吞噬”1,2,3或任何你喜欢的数字,然后留下下一组来取你正在寻找的那个。

代替+,您还可以使用{1,}表示1对任意数字。

如果您的块可以为零,那么:

ABC - GHI-JKL

你想要找到第二个,即“”(空字符串),然后使用*而不是+。或者你可以使用{0,},意思是0到任意数字。

答案 1 :(得分:1)

您没有指定您正在使用的语言/正则表达式引擎,但有些(大多数?)允许您反复将匹配反复应用于同一个字符串。例如,pcrecpp允许您执行:

pcrecpp::StringPiece piece("ABC-DEF-GHI-JKL-MNO");
pcrecpp::RE re("([^-]+)-?");
unsigned int index = 3; // e.g., for GHI

std::string group;
for(unsigned int i = 0; i < index; i++)
    re.Consume(&piece, &group);

// group now contains "GHI". Calling Consume again would give it JKL

答案 2 :(得分:0)

基于您的修订的不同答案:您只想要这个吗?

(?:[^-]+-){index-1}([^-]+)

非捕获组匹配子块的index-1,因此index=3匹配ABC-DEF01-,然后捕获组匹配GHI54677