我正在寻找一种方法来使python re模块或更新的正则表达式模块的finditer功能匹配特定模式的所有可能变体,重叠或其他。我知道使用lookaheads来获取匹配而不消耗搜索字符串,但我仍然只获得一个正则表达式,每个索引,我可以得到多个。
我正在使用的正则表达式是这样的:
(?=A{2}[BA]{1,6}A{2})
所以在字符串中:
AABAABBAA
它应该能够匹配:
AABAA
AABAABBAA
AABBAA
但目前它只会匹配最后两个。我意识到这与[BA]{1,6}
的贪婪有关。有没有办法让正则表达式从最懒惰到最贪婪的模式匹配?
答案 0 :(得分:1)
您将无法使用finditer()
或任何正常的导航方式。我管理它的唯一方法(使用Java而不是Python)是通过手动迭代源字符串的每个唯一子字符串(由起始位置和长度确定),以正常方式将正则表达式应用于每个子字符串(不是使用外观) ),并固定在两端。
Java的Matcher类使用region()
方法提供了一种方便的方法。它允许您假装源的任何子串实际上都是整个事物,而不必生成新的String对象。并且matches()
方法会自动锚定两端的匹配,因此您根本不需要修改正则表达式。
我很确定Python的re
模块不支持这样的功能,但是在另一个模块中可能会有一些东西可以用来产生类似的效果(我不熟悉Python,所以这只是乐观)。我对regex
模块更不熟悉,但它似乎支持所有其他风格的最甜蜜的功能,所以值得一看。
这是我的Java解决方案,以防您感兴趣:
public static void printAllMatches(String text, String regex)
{
System.out.printf("%s results:%n", text);
Matcher m = Pattern.compile(regex).matcher(text);
int end = text.length();
for (int i = 0; i < end; ++i)
{
for (int j = i + 1; j <= end; ++j)
{
m.region(i, j);
if (m.matches())
{
for (int k = 0; k < i; k++)
{
System.out.print(" ");
}
System.out.println(m.group());
}
}
}
}
输出:
AABAABBAA results:
AABAA
AABAABBAA
AABBAA
答案 1 :(得分:1)
I realise it is to do with the greediness of the [BA]{1,6}. Is there a way to make the regex match everything from the laziest to the greediest possible pattern?
问题是双重的。
1. Regex engines will only match once at a character position.
2. There is not a regex construct of between lazy and greedy
it's either one or the other.
跳过问题1.暂时..,
问题2 :
可能存在{1,6}
1,2,3,4,5或6匹配的情况
在给定位置的构造(字符)。
要解决该问题,您必须指定独立的{1},{2},{3},{4},{5},{6}
作为该位置的可选替换。
显然,范围 {1,6}
无效。
就 Range 而言,可以指定它来找到
通过添加惰性修饰符{1,6}?
来增加最小量
但这只能找到最小的数量,不多也不少。
最后,
问题1 :
当正则表达式引擎匹配时,总是向前推进当前位置
金额等于最后一场比赛的长度
在匹配的零长度断言的情况下,它人为地增加了
一个角色向前的位置。
因此,考虑到这两个问题,可以利用这些优势/劣势来实现这一目标 一个解决方法,并不得不忍受一些副作用。
<强>变通方法强>:
将所有可能的替代方案放在一个位置作为要分析的断言。
某个位置的每个匹配将包含一个包含变体的组列表
因此,如果您匹配6个可能的变体组中的3个变体,则具有值的组将是变体。
如果没有任何组具有值,则在该位置找不到变体
不会发生任何变体,因为所有断言都是可选的
为了避免在这些特定位置进行不必要的匹配,最后一个
条件可用于不报告这些内容。 (即(?(1)|(?(2)|(?!)))
等。)。
让我们使用您的范围示例作为示例
我们将在末尾使用条件来验证匹配的组,
但没有它就可以完成。
_注意使用此范围示例导致重叠相同的
最终匹配中的值。这确实不确保了唯一的匹配
一个位置(下面的例子显示了如何避免这种情况)。
# (?=(A{2}[BA]{1,6}?A{2}))?(?=(A{2}[BA]{1,6}A{2}))?(?(1)|(?(2)|(?!)))
(?=
( # (1 start)
A{2}
[BA]{1,6}?
A{2}
) # (1 end)
)?
(?=
( # (2 start)
A{2}
[BA]{1,6}
A{2}
) # (2 end)
)?
(?(1)
| (?(2)
| (?!)
)
)
输出:
** Grp 1 - ( pos 0 , len 5 )
AABAA
** Grp 2 - ( pos 0 , len 9 )
AABAABBAA
-------------
** Grp 1 - ( pos 3 , len 6 )
AABBAA
** Grp 2 - ( pos 3 , len 6 )
AABBAA
相同,但没有范围问题 在这里,我们明确定义了独特的结构 请注意每个位置的唯一值。
# (?=(A{2}[BA]{1}A{2}))?(?=(A{2}[BA]{2}A{2}))?(?=(A{2}[BA]{3}A{2}))?(?=(A{2}[BA]{4}A{2}))?(?=(A{2}[BA]{5}A{2}))?(?=(A{2}[BA]{6}A{2}))?(?(1)|(?(2)|(?(3)|(?(4)|(?(5)|(?(6)|(?!)))))))
(?=
( # (1 start)
A{2}
[BA]{1}
A{2}
) # (1 end)
)?
(?=
( # (2 start)
A{2}
[BA]{2}
A{2}
) # (2 end)
)?
(?=
( # (3 start)
A{2}
[BA]{3}
A{2}
) # (3 end)
)?
(?=
( # (4 start)
A{2}
[BA]{4}
A{2}
) # (4 end)
)?
(?=
( # (5 start)
A{2}
[BA]{5}
A{2}
) # (5 end)
)?
(?=
( # (6 start)
A{2}
[BA]{6}
A{2}
) # (6 end)
)?
(?(1)|(?(2)|(?(3)|(?(4)|(?(5)|(?(6)|(?!)))))))
输出:
** Grp 1 - ( pos 0 , len 5 )
AABAA
** Grp 2 - NULL
** Grp 3 - NULL
** Grp 4 - NULL
** Grp 5 - ( pos 0 , len 9 )
AABAABBAA
** Grp 6 - NULL
------------------
** Grp 1 - NULL
** Grp 2 - ( pos 3 , len 6 )
AABBAA
** Grp 3 - NULL
** Grp 4 - NULL
** Grp 5 - NULL
** Grp 6 - NULL
最后,您需要做的就是在每场比赛中抓住抓取组 使用值,并将它们放入数组中。
答案 2 :(得分:-2)
此正则表达式正确匹配3个字符串:
AABAA AABAABBAA AABBAA
((^(AA){1}(BAA)$){1})|(((AA){1}(BB){1}(AA){1}$){1})
如果你想在字符串&#34; AABAABBAA&#34;中搜索这些子字符串。使用python你可以使用方法&#34;搜索&#34; :
re.search('AABAABB','AABAABBAA')
re.search('AABAABBAA','AABAABBAA')
re.search('AABBAA','AABAABBAA')