找出正则表达式各部分匹配的内容

问题描述 投票:0回答:3

我有数百个(相当简单)的正则表达式及其在大量序列中的匹配项。我想知道每个正则表达式的哪个部分与目标序列中的哪个位置匹配。例如,以下正则表达式“ [DSTE] [^ P] [^ DEWHFYC] D [GSAN]”可以按以下顺序与位置4到8匹配:

ABC SGADA ZZZ

[我想(以编程方式)得出的结果是,对于每个正则表达式,是1)正则表达式的每个“部分”,以及2)与其匹配的目标序列中的位置:

[DSTE] -- (3, 4),
[^P] -- (4, 5),
[^DEWHFYC] -- (5, 6),
D -- (6, 7),
[GSAN] -- (7, 8)

[我找到了这个网站,该网站基本上可以实现我想要的功能:https://regex101.com/,但是我不确定我必须深入研究正则表达式解析才能在自己的代码中完成此操作(我正在使用Python和R)。

python regex grammar text-parsing
3个回答
0
投票

如果要提取与正则表达式各部分匹配的字符串的位置,则应该用()覆盖它们,以使每段成为捕获组。如果不这样做,您将无法分析正则表达式各部分匹配的位置。

([DSTE])([^P])([^DEWHFYC])(D)([GSAN])

现在,您可以看到每个部分都是分开的。因此,正则表达式的每个部分可以使用另一个正则表达式来提取

\((.*?)(?=\)(?:\(|$))

Bonus:您还可以按正则表达式的每个部分提取匹配的文本部分

因此,使用re.search(pattern, text, flags = 0)方法获取所需的数据,如下所示

re.search(pattern, text, flags = 0)

import re text = 'ABCSGADAZZZ' theRegex = r'([DSTE])([^P])([^DEWHFYC])(D)([GSAN])' r1 = re.compile(r'\((.*?)(?=\)(?:\(|$))') # each part extractor r2 = re.compile(theRegex) # your regex grps = r1.findall(theRegex) # parts of regex m = re.search(r2, text) for i in range(len(grps)): print( 'Regex: {} | Match: {} | Range: {}'.format(grps[i], m.group(i+1), m.span(i+1)) )


0
投票

使用Live Example包,您应该可以像这样组合:

stringr

然后组合函数输出或编写一个简单的包装函数


0
投票

我从未见过具有此类功能的正则表达式引擎在其API中公开。还是没有意识到这样的API。在[[R或Python中可能有一个,但不是必需的。

但是无论如何,这并不像我想的那么简单。

考虑正则表达式> stringr::str_match_all(string = "ABCSGADAZZZ", pattern = "[DSTE][^P][^DEWHFYC]D[GSAN]") [[1]] [,1] [1,] "SGADA" > stringr::str_locate_all(string = "ABCSGADAZZZ", pattern = "[DSTE][^P][^DEWHFYC]D[GSAN]") [[1]] start end [1,] 4 8 而不是/(a(b*))*/"abbabbb"部分匹配的不仅仅是单个子字符串。相反,可能有一个子字符串与某些正则表达式的不止一部分匹配。

即使您的正则表达式“相当简单” ...它们真的真的像问题中的那个一样简单吗?

正如其他人已经提到的,您可以使用捕获组来找出哪个组与之匹配,但是为此,您需要自己编辑正则表达式并跟踪组的不确定性。或者,是的,编写自己的解析器。因为正则表达式无法解析正则表达式-它们不足以支持自己的语法。

...嗯,如果它们真的很简单,或多或少是统一的,也许有一种方法可以自动轻松地解析和修改所有正则表达式(以添加捕获组)。但是,不可能仅给出正则表达式的一个例子。

...但是您可能在问一个错误的问题:b*

许多张贴者陷入的陷阱是问如何实现某个“小”目标,但不要说更大的目标是什么。通常,较小的目标是不可能的,或者很少是一个好主意–相反,需要使用其他方法

更新:

我对示例字符串和正则表达式做了一些更改,以解决您在评论中提到的https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/情况

这里是修改P{1,3} es并获得所需输出的代码:

regex

它将给您:

import re

orig_re = "[DSTE]{1,1}[^P][^DEWHFYC]DP{1,3}[GSAN]"
mod_re = r'((\[.*?\]|.)(\{.*?\})?)'
groups = re.findall(mod_re, orig_re)
print("parts of regex:", [g[0] for g in groups])
new_regex_str = re.sub(mod_re, r'(\1)', orig_re)
print("new regex with capturing groups:", new_regex_str)
new_re = re.compile(new_regex_str)
str = "ABCSGADPPAZZZSGADPA"
matches = new_re.finditer(str)
for m in matches:
    print( '----------')
    for g in range(len(groups)):
        print('#{}: {} -- {}'.format(g, groups[g][0], m.span(g+1)))

也在JS中

 

parts of regex: ['[DSTE]{1,1}', '[^P]', '[^DEWHFYC]', 'D', 'P{1,3}', '[GSAN]'] new regex with capturing groups: ([DSTE]{1,1})([^P])([^DEWHFYC])(D)(P{1,3})([GSAN]) ---------- #0: [DSTE]{1,1} -- (3, 4) #1: [^P] -- (4, 5) #2: [^DEWHFYC] -- (5, 6) #3: D -- (6, 7) #4: P{1,3} -- (7, 9) #5: [GSAN] -- (9, 10) ---------- #0: [DSTE]{1,1} -- (13, 14) #1: [^P] -- (14, 15) #2: [^DEWHFYC] -- (15, 16) #3: D -- (16, 17) #4: P{1,3} -- (17, 18) #5: [GSAN] -- (18, 19)
© www.soinside.com 2019 - 2024. All rights reserved.