如何捕获多个重复组?

时间:2016-05-03 12:02:57

标签: regex swift nsregularexpression regex-greedy regex-group

我需要捕获相同模式的多个组。假设,我有一个以下字符串:

^(?:([A-Z]+),?)+$

我写了一个以下模式

split

我想要它做的是,捕获每一个单词,以便第1组是:“HELLO”,第2组是“THERE”而第3组是“WORLD”我的正则表达式实际上只捕获了最后一个,这是“世界”。

我正在测试我的正则表达式here,我想在Swift中使用它(也许在Swift中有一种方法可以获得中间结果,以便我可以使用它们?)

更新:我不想使用if (Schema::hasTable('users')) { Schema::table('users', function (Blueprint $table) { if (Schema::hasColumn('users', 'active')) { $table->integer('active')->default(0)->change(); } }); } 。我现在只需要捕捉所有匹配模式的组,而不仅仅是最后一组。

9 个答案:

答案 0 :(得分:25)

在模式中有一个组,您只能在该组中获得一个确切的结果。如果您的捕获组被模式重复(您在周围的非捕获组中使用了$connection = ssh2_connect('http://www.***.com:/tmp', 22); ssh2_auth_password($connection, 'root', ''); ssh2_scp_send($connection, '/upload', 'www.***.com:/tmp', 0777); 量词),则只存储与其匹配的最后一个值。

你必须使用你的语言的正则表达式实现函数找到模式的所有匹配,然后你必须删除非捕获组的锚点和量词(你可以省略非捕获组本身也是如此。

或者,展开你的正则表达式,让模式包含你想要在结果中获得的每个组的一个捕获组:

+

答案 1 :(得分:1)

只是在答案中提供第2段的其他例子。我不确定你在一场比赛中获得三组而不是使用一组的三场比赛是多么重要。例如,在groovy中:

def subject = "HELLO,THERE,WORLD"
def pat = "([A-Z]+)"
def m = (subject =~ pat)
m.eachWithIndex{ g,i ->
  println "Match #$i: ${g[1]}"
}

Match #0: HELLO
Match #1: THERE
Match #2: WORLD

答案 2 :(得分:1)

您实际上有一个捕获组,该捕获组将匹配多次。没有多个捕获组。

javascript(js)解决方案:

let string = "HI,THERE,TOM";
let myRegexp = /([A-Z]+),?/g;       //modify as you like
let match = myRegexp.exec(string);  //js function, output described below
while(match!=null){                 //loops through matches
    console.log(match[1]);          //do whatever you want with each match
    match = myRegexp.exec(bob);     //find next match
}

输出:

HI
THERE
TOM

语法:

// matched text: match[0]
// match start: match.index
// capturing group n: match[n]

如您所见,这将适用于任意数量的比赛。

答案 3 :(得分:0)

我认为您需要这样的东西。...

b="HELLO,THERE,WORLD"
re.findall('[\w]+',b)

Python3中哪个会返回

['HELLO', 'THERE', 'WORLD']

答案 4 :(得分:0)

阅读Byte Commander's answer之后,我想介绍一个可能的改进:

只要您的n是预先确定的,您就可以生成与n个单词匹配的正则表达式。例如,如果我想匹配1到3个单词,则使用regexp:

^([A-Z]+)(?:,([A-Z]+))?(?:,([A-Z]+))?$

将匹配具有一个,两个或三个捕获组的下一个句子。

HELLO,LITTLE,WORLD
HELLO,WORLD
HELLO

您可以看到有关此正则表达式on Regex101的完整详细说明。

正如我所说,使用您喜欢的语言为您想要的任何组生成此正则表达式都非常容易。由于我不是一个敏捷的人,所以下面是一个红宝石示例:

def make_regexp(group_regexp, count: 3, delimiter: ",")
  regexp_str = "^(#{group_regexp})"
  (count - 1).times.each do
    regexp_str += "(?:#{delimiter}(#{group_regexp}))?"
  end
  regexp_str += "$"
  return regexp_str
end

puts make_regexp("[A-Z]+")

话虽如此,我建议您不要使用正则表达式,根据您的需要,还有许多其他出色的工具,从简单的split到某些标记化模式。恕我直言,正则表达式不是其中之一。例如在红宝石中,我将使用str.split(",")str.scan(/[A-Z]+/)

之类的东西

答案 5 :(得分:0)

我知道我的答案来晚了,但是今天我却遇到了,我用以下方法解决了它:

^(([A-Z]+),)+([A-Z]+)$

因此,第一组 (([A-Z]+),)+ 将匹配所有重复的模式,但最后一个 ([A-Z]+) 除外,这将匹配最后一个。不管字符串中有多少个重复的组,这都是动态的。

答案 6 :(得分:0)

抱歉,不是Swift,这只是用最接近的语言进行的概念验证。

Environment

注意:如果您真的要使用此功能,则应使用正则表达式匹配函数给定的匹配位置,而不是字符串替换。

答案 7 :(得分:0)

主要区别是重复捕获的组,而不是捕获重复的组

您已经发现,区别在于重复捕获的组仅捕获最后一次迭代。捕获重复的组将捕获所有迭代。

在PCRE(PHP)中:

((?:\w+)+),?
Match 1, Group 1.    0-5      HELLO
Match 2, Group 1.    6-11     THERE
Match 3, Group 1.    12-20    BRUTALLY
Match 4, Group 1.    21-26    CRUEL
Match 5, Group 1.    27-32    WORLD

由于所有捕获物都在第1组中,因此您只需$1进行替换。

我使用了以下正则表达式的一般形式:

((?:{{RE}})+)

示例regex101

答案 8 :(得分:0)

  1. 设计一个匹配列表中每个特定元素而不是整个列表的正则表达式。用 /g
  2. 应用它
  3. 遍历匹配项,清除混入的任何垃圾(例如列表分隔符)。您可能需要另一个正则表达式,或者您可以使用简单的替换子字符串方法。

示例代码是用 JS 编写的,抱歉 :) 思路一定很清楚。

    const string = 'HELLO,THERE,WORLD';

    // First use following regex matches each of the list items separately:
    const captureListElement = /^[^,]+|,\w+/g;
    const matches = string.match(captureListElement);

    // Some of the matches may include the separator, so we have to clean them:
    const cleanMatches = matches.map(match => match.replace(',',''));

    console.log(cleanMatches);