具有不同量词的正则表达式捕获组
Regex capture group with different quantifiers
我正在解析的文本包括捕获组前后以及捕获组内的星号。我确定用于解析捕获组的模式是 basically:The 文本前的连续星号将始终至少为 30 个。同样,最后一个单词之后的连续星号将至少有 15 个字符长。捕获组中的连续星号将始终低于 10.The 我遇到的问题是我不确定如何为捕获组中的星号与组中的其他字符提供不同的量词,但包括它在同一个匹配集中。例如:
text = 'ÿÿÿÿ*************************************************CURRICULUM VITAE***Información *personal*********************ìÌ**Ì*Ì*Ì*'
所以基本上,我只需要捕获文本部分。星号可以存在于实际文本之前和之后(我可以稍后删除),但乱码不能。所以要么输出工作:
#Output #1
CURRICULUM VITAE***Información *personal
#output #2
**********CURRICULUM VITAE***Información *personal**********
下面是我试过的无法区分捕获组和后续乱码的代码。不过,它确实正确识别了文本前的星号。
p=re.compile(r'(?<=[*]{30})([\x29{,10}|\u00c0-\u00d6|\u00d8-\u00f6|\u00f8-\u02af|\u1d00-\u1d25|\u1d62-\u1d65|\u1d6b-\u1d77|\u1d79-\u1d9a|\u1e00-\u1eff|\u2090-\u2094|\u2184-\u2184|\u2488-\u2490|\u271d-\u271d|\u2c60-\u2c7c|\u2c7e-\u2c7f|\ua722-\ua76f|\ua771-\ua787|\ua78b-\ua78c|\ua7fb-\ua7ff|\ufb00-\ufb06|\x20-\x2A|\x2B-\x7E]+)(?=[*]{,15})', re.MULTILINE)
print(re.findall(p, text)[0])
#output
*******************CURRICULUM VITAE***Información *personal*********************ìÌ**Ì*Ì*Ì*
可以看到,成功切断了实际捕获组之前的乱码,但是没有切断捕获组之后的乱码。我猜上面的正则表达式写得不正确,所以 \x29{,10} 与其余字符一起执行,可以有 + 出现。
请注意,\x29 是 * 的 unicode。更改 unicode 字符作为解析捕获组的方式不是一种选择,我需要能够保持重音,这也可能存在于乱码部分。
根据 MAX XAPI 的评论进行编辑
在乱码之后可能存在 15 个以上的连续星号,因此您的代码似乎在最后 15 个以上的连续星号处被截断,但保留了之前的星号。所以我需要的是匹配要么在前 15 个连续的星号处切入(即,捕获组后没有星号),要么只包括捕获组后的前 15 个星号。例如:
p=re.compile(r'(?<=[*]{30})([^*][\x2A{,10}|\u00c0-\u00d6|\u00d8-\u00f6|\u00f8-\u02af|\u1d00-\u1d25|\u1d62-\u1d65|\u1d6b-\u1d77|\u1d79-\u1d9a|\u1e00-\u1eff|\u2090-\u2094|\u2184-\u2184|\u2488-\u2490|\u271d-\u271d|\u2c60-\u2c7c|\u2c7e-\u2c7f|\ua722-\ua76f|\ua771-\ua787|\ua78b-\ua78c|\ua7fb-\ua7ff|\ufb00-\ufb06|\x20-\x2A|\x2B-\x7E]+[^*])(?=[*]{15,})',re.MULTILINE)
text=t='ÿÿÿÿ*************************************************CURRICULUM VITAE***Información *personal**********************ìÌ**Ì*Ì*Ì*************************************(ìÌ**Ì*Ì*Ì***************'
#output
print(re.findall(p, text))
['CURRICULUM VITAE***Información *personal**********************ìÌ**Ì*Ì*Ì']
#desired output
['CURRICULUM VITAE***Información *personal']
The following is also acceptable
['CURRICULUM VITAE***Información *personal***************']
考虑到捕获组必须以不同于 *
的其他方式开始并且必须以相同的方式结束,您可以使用一个技巧。因此,只需添加另一个容器组,其中包含两个 [^*]
:
(?<=[*]{30})([^*][\x29{,10}|\u00c0-\u00d6|\u00d8-\u00f6|\u00f8-\u02af|\u1d00-\u1d25|\u1d62-\u1d65|\u1d6b-\u1d77|\u1d79-\u1d9a|\u1e00-\u1eff|\u2090-\u2094|\u2184-\u2184|\u2488-\u2490|\u271d-\u271d|\u2c60-\u2c7c|\u2c7e-\u2c7f|\ua722-\ua76f|\ua771-\ua787|\ua78b-\ua78c|\ua7fb-\ua7ff|\ufb00-\ufb06|\x20-\x2A|\x2B-\x7E]+[^*])(?=[*]{15,})
我 added/changed:
- 在捕获组的末尾和开头添加了两次“非
*
”:([^*] ... [^*])
- 在结束时将
{,15}
更改为 {15,}
(因此“至少出现 15 次”而不是“最多出现 15 次”)
这只使用了一个否定的先行断言:
尝试:
\*{30,}((?:[^*]|\*(?!\*{9}))+?)\*{15,}
\*{30,}
匹配 30 个或更多星号
(
捕获组 1 开始
(?:[^*]|\*(?!\*{9}))+?
匹配 non-capture 组中的一个或多个:一个 non-asterisk 或一个星号后不跟另外 9 个星号
- `)' 捕获组 1 结束
\*{15,}
匹配 15 个或更多星号
import re
text = 'ÿÿÿÿ*************************************************CURRICULUM VITAE***Información *personal*********************ìÌ**Ì*Ì*Ì*'
l = re.findall(r'\*{30,}((?:[^*]|\*(?!\*{9}))+?)\*{15,}', text)
print(l)
打印:
['CURRICULUM VITAE***Información *personal']
我正在解析的文本包括捕获组前后以及捕获组内的星号。我确定用于解析捕获组的模式是 basically:The 文本前的连续星号将始终至少为 30 个。同样,最后一个单词之后的连续星号将至少有 15 个字符长。捕获组中的连续星号将始终低于 10.The 我遇到的问题是我不确定如何为捕获组中的星号与组中的其他字符提供不同的量词,但包括它在同一个匹配集中。例如:
text = 'ÿÿÿÿ*************************************************CURRICULUM VITAE***Información *personal*********************ìÌ**Ì*Ì*Ì*'
所以基本上,我只需要捕获文本部分。星号可以存在于实际文本之前和之后(我可以稍后删除),但乱码不能。所以要么输出工作:
#Output #1
CURRICULUM VITAE***Información *personal
#output #2
**********CURRICULUM VITAE***Información *personal**********
下面是我试过的无法区分捕获组和后续乱码的代码。不过,它确实正确识别了文本前的星号。
p=re.compile(r'(?<=[*]{30})([\x29{,10}|\u00c0-\u00d6|\u00d8-\u00f6|\u00f8-\u02af|\u1d00-\u1d25|\u1d62-\u1d65|\u1d6b-\u1d77|\u1d79-\u1d9a|\u1e00-\u1eff|\u2090-\u2094|\u2184-\u2184|\u2488-\u2490|\u271d-\u271d|\u2c60-\u2c7c|\u2c7e-\u2c7f|\ua722-\ua76f|\ua771-\ua787|\ua78b-\ua78c|\ua7fb-\ua7ff|\ufb00-\ufb06|\x20-\x2A|\x2B-\x7E]+)(?=[*]{,15})', re.MULTILINE)
print(re.findall(p, text)[0])
#output
*******************CURRICULUM VITAE***Información *personal*********************ìÌ**Ì*Ì*Ì*
可以看到,成功切断了实际捕获组之前的乱码,但是没有切断捕获组之后的乱码。我猜上面的正则表达式写得不正确,所以 \x29{,10} 与其余字符一起执行,可以有 + 出现。
请注意,\x29 是 * 的 unicode。更改 unicode 字符作为解析捕获组的方式不是一种选择,我需要能够保持重音,这也可能存在于乱码部分。
根据 MAX XAPI 的评论进行编辑
在乱码之后可能存在 15 个以上的连续星号,因此您的代码似乎在最后 15 个以上的连续星号处被截断,但保留了之前的星号。所以我需要的是匹配要么在前 15 个连续的星号处切入(即,捕获组后没有星号),要么只包括捕获组后的前 15 个星号。例如:
p=re.compile(r'(?<=[*]{30})([^*][\x2A{,10}|\u00c0-\u00d6|\u00d8-\u00f6|\u00f8-\u02af|\u1d00-\u1d25|\u1d62-\u1d65|\u1d6b-\u1d77|\u1d79-\u1d9a|\u1e00-\u1eff|\u2090-\u2094|\u2184-\u2184|\u2488-\u2490|\u271d-\u271d|\u2c60-\u2c7c|\u2c7e-\u2c7f|\ua722-\ua76f|\ua771-\ua787|\ua78b-\ua78c|\ua7fb-\ua7ff|\ufb00-\ufb06|\x20-\x2A|\x2B-\x7E]+[^*])(?=[*]{15,})',re.MULTILINE)
text=t='ÿÿÿÿ*************************************************CURRICULUM VITAE***Información *personal**********************ìÌ**Ì*Ì*Ì*************************************(ìÌ**Ì*Ì*Ì***************'
#output
print(re.findall(p, text))
['CURRICULUM VITAE***Información *personal**********************ìÌ**Ì*Ì*Ì']
#desired output
['CURRICULUM VITAE***Información *personal']
The following is also acceptable
['CURRICULUM VITAE***Información *personal***************']
考虑到捕获组必须以不同于 *
的其他方式开始并且必须以相同的方式结束,您可以使用一个技巧。因此,只需添加另一个容器组,其中包含两个 [^*]
:
(?<=[*]{30})([^*][\x29{,10}|\u00c0-\u00d6|\u00d8-\u00f6|\u00f8-\u02af|\u1d00-\u1d25|\u1d62-\u1d65|\u1d6b-\u1d77|\u1d79-\u1d9a|\u1e00-\u1eff|\u2090-\u2094|\u2184-\u2184|\u2488-\u2490|\u271d-\u271d|\u2c60-\u2c7c|\u2c7e-\u2c7f|\ua722-\ua76f|\ua771-\ua787|\ua78b-\ua78c|\ua7fb-\ua7ff|\ufb00-\ufb06|\x20-\x2A|\x2B-\x7E]+[^*])(?=[*]{15,})
我 added/changed:
- 在捕获组的末尾和开头添加了两次“非
*
”:([^*] ... [^*])
- 在结束时将
{,15}
更改为{15,}
(因此“至少出现 15 次”而不是“最多出现 15 次”)
这只使用了一个否定的先行断言:
尝试:
\*{30,}((?:[^*]|\*(?!\*{9}))+?)\*{15,}
\*{30,}
匹配 30 个或更多星号(
捕获组 1 开始(?:[^*]|\*(?!\*{9}))+?
匹配 non-capture 组中的一个或多个:一个 non-asterisk 或一个星号后不跟另外 9 个星号- `)' 捕获组 1 结束
\*{15,}
匹配 15 个或更多星号
import re
text = 'ÿÿÿÿ*************************************************CURRICULUM VITAE***Información *personal*********************ìÌ**Ì*Ì*Ì*'
l = re.findall(r'\*{30,}((?:[^*]|\*(?!\*{9}))+?)\*{15,}', text)
print(l)
打印:
['CURRICULUM VITAE***Información *personal']