Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中捕获重复模式_Python_Regex - Fatal编程技术网

在Python中捕获重复模式

在Python中捕获重复模式,python,regex,Python,Regex,我正在尝试为Python日志格式化程序实现某种类似标记的行为 让我们以这个字符串为例: **这是一个警告**:病毒管理器失败 几个正则表达式之后,字符串失去了类似markdown的语法,并被转换为bash代码: \033[33m\033[1M这是一个警告\033[0m:病毒管理器\033[4M失败\033[0m\033[0m 但这应该压缩到 \033[33;1M这是一个警告\033[0m:病毒管理器\033[4M失败\033[0m 除了许多其他无效的解决方案外,我还尝试了以下方法: (\\033

我正在尝试为Python日志格式化程序实现某种类似标记的行为

让我们以这个字符串为例:

**这是一个警告**:病毒管理器失败

几个正则表达式之后,字符串失去了类似markdown的语法,并被转换为bash代码:

\033[33m\033[1M这是一个警告\033[0m:病毒管理器\033[4M失败\033[0m\033[0m

但这应该压缩到

\033[33;1M这是一个警告\033[0m:病毒管理器\033[4M失败\033[0m

除了许多其他无效的解决方案外,我还尝试了以下方法:

(\\033\[([\d]+)m{2,}
=>捕获:
\033[33m\033[1m
带g1'\033[1m'和g2'1',
\033[0m
带g1'\033[0m'和g2'0'

(\\033\[([\d]+)m)+
很多结果,不正常

(?:(\\033\[([\d]+)m)+
许多结果,尽管如果我理解正确,这是重复模式的推荐方法,但不正常

和其他

我的目标是取得以下成果:

输入
\033[33m\033[1M这是一个警告\033[0m:病毒管理器\033[4M失败\033[0m\033[0m

输出

匹配1
033[33m\033[1m

第1组:33

第2组:1

第二场比赛
033[0m\033[0m

第1组:0

第2组:0


换句话说,捕获那些“重复的”不仅仅是那些,所以我可以将它们与regex sub融合。

这对于您在这里描述的情况非常简单;只需从左到右写出您想要匹配和捕获的内容。重复捕获块在这里对您没有帮助,因为结果只会返回最近捕获的值

\\033\[(\d+)m\\033\[(\d+)m

要修改的字符串中的模式还没有从问题中弄清楚。例如,
033
是固定的还是可能是
025
甚至是
25
?我在使用正则表达式时做了一些假设

r" ^(\\0(\d+)\[\2)[a-z]\\0\2\[(\d[a-z].+)
为了获得两个要合并的捕获组,它们之间用分号分隔。我试图在下面阐明我的假设,部分是为了帮助OP修改此正则表达式以满足其他要求

正则表达式执行以下操作:

^           # match beginning of line
(           # begin cap grp 1
  \\0       # match '\0'
  (\d+)     # match 1+ digits in cap grp 2
  \[        # match '['
  \2        # match contents of cap grp 2
)           # end cap grp 1
[a-z]       # match a lc letter
\\0         # match '\0'      
\2          # match contents of cap grp 2
\[          # match '['
(\d[a-z].+) # match a digit, then lc letter then 1+ chars to the
            #   end of the line in cap grp 3
如您所见,在组1中捕获的字符串部分是

\033[33
我假设这个字符串现在是
033
的部分必须是两个或更多以零开头的数字,并且数字字符串的第二次出现由零后面的相同数字组成。这是通过捕获“0”后面的数字来完成的(
33
)在捕获组2中,然后使用反向引用
\2

字符串的下一部分将被替换,因此不会被捕获:

m\\033[
我假设
m
必须是一个小写字母(或者应该是一个文本
m
?),反斜杠、零和必需数字以及以下数字必须再次与捕获组2的内容匹配

字符串的其余部分

1mThis is a warning\033[0m: Virus manager \033[4mfailed\033[0m\033[0m
是在捕获组3中捕获的。在这里,我假设它以一个数字开头(可能应该是
\d+
),后跟一个小写字母,不必与前面匹配的小写字母相同(尽管可以用另一个捕获组强制执行)。此时,我将该行的其余部分与
+
匹配,并放弃了该部分字符串中的匹配模式


或者,一个可能只有两个捕获组,捕获组现在是2,变成1,#2是字符串中要用分号替换的部分。

您希望连续匹配重复的
\033[\d+m
文本块,并用分号连接
[
后面的数字

你可以用

re.sub(r'(?:\\033\[\d+m){2,}', lambda m: r'\033['+";".join(set(re.findall(r"\[(\d+)", m.group())))+'m', text)


(?:\\033\[\d+m){2,}
模式将匹配两个或多个
\033[
+一个或多个数字+
m
文本块,然后,匹配将传递到lambda表达式,其中输出为:1)
\033[
,2)使用
re.findall(r)\[(\d+)提取的
[/code>之后的所有数字,m.group())
并用
集消除重复,然后3)
m

有很多不必要的信息,你能发布一个示例输入和预期的输出吗?它在末尾…输入:\033[33;1这是一个警告\033[0m:Virus manager\033[4mfiled\033[0m输出读取消息的结尾表达式创建的匹配组数始终是一个设定值。例如,
(…)+
将只生成一个匹配组。这不是100%清楚:规则是什么?您是否有
\033[33m\033[1m\033[22m
?如果是,预期的输出是什么?请尝试
re.sub(r'(?:\\033\[\d+m{2,}',lambda m:r'\033['+“;”.join(set(re.findall(r“\[(\d+),m.group()))+'m',text)
谢谢,但这只对两个连续的,而不是随机的N个连续的序列有效。我的观点是,这样做不是用一个表达式和重复的捕获组。通常使用一个表达式来获取整个序列,一秒钟(或字符串函数)从中获取一个数字列表和一些处理值的逻辑——如Wiktor Stribiżew的回答。感谢您的详细解释!我将尽快测试并返回结果!