python - 如何使用 '?' 在python 中提取两个匹配模式之间的可选子字符串?
问题描述
我正在回答这个问题。考虑这个字符串
str1 = '{"show permission allowed to 16": "show permission to 16\\nSchool permissions from group 17:student to group 16:teacher:\\n\\tAllow ALL-00\\nSchool permissions from group 18:library to group 16(Temp):teacher:\\n\\tNo Allow ALL-00\\nSchool permissions from group 20:Gym to group 16:teacher:\\n\\tCheck ALL-00\\nRTYAHY: FALSE\\nRTYAHY: FALSE\\n\\n#"}'
并假设我想在每个子字符串from group
和\\t
具有最小匹配字符串之后的子字符串之后提取数字。
我用下面的正则表达式做到了这一点
import re
res = re.findall(r'from group (\d+).*?\\t(.*? ALL-..)', str1)
输出是:
[('17', 'Allow ALL-00'), ('18', 'No Allow ALL-00'), ('20', 'Check ALL-00')]
现在在我提取的每个子字符串之间(数字和 之后的子字符串\t
)可能有一个可选的子字符串,它的值是Temp
我想要提取的(如果存在)。例如,在18
和之间No Allow ALL-00
有Temp
我想提取的子字符串。
我尝试使用?
如下:
res = re.findall(r'from group (\d+).*?(Temp)?.*?\\t(.*? ALL-..)', str1)
但结果元组的相应第二个元素始终为空:
[('17', '', 'Allow ALL-00'), ('18', '', 'No Allow ALL-00'), ('20', '', 'Check ALL-00')]
虽然我期待类似的东西:
[('17', '', 'Allow ALL-00'), ('18', 'Temp', 'No Allow ALL-00'), ('20', '', 'Check ALL-00')]
在这种情况下如何提取子字符串?我在做什么错误?
还有一个问题:假设我希望我的结果列表没有这个元素(包含 的那个Temp
):我应该只使用[^]
然后使用相应的匹配模式吗?
解决方案
它未捕获的原因Temp
是因为您已将其设为可选,因为它.*?
会消耗它,并且Temp
不会在您的可选组中捕获。
为了解决这个问题,您可以使用否定前瞻来拒绝Temp
被捕获,但使用此正则表达式的任何其他字符除外,
from group (\d+)(?:(?!Temp).)*?(Temp)?(?:(?!Temp).)*?\\t(.*? ALL-..)
^^^^^^^^^ This rejects Temp getting captured except any other character
正则表达式解释:
from group
- 此文本的字面匹配(?:(?!Temp).)*?
-?:
表示它是一个非捕获组,默认情况下是一个捕获组,这意味着捕获任何内容,但在您看到Temp
字符串时会停止,这*
意味着捕获零个或多个字符。所以这会捕获任何不包含Temp
并且?
意味着尽可能少的字符串(Temp)?
- 可选择捕获(Temp
如果存在)(?:(?!Temp).)*?
- 再次捕获任何字符零次或多次,除了Temp
上面一样\\t
- 从字面上捕捉这一点(.*? ALL-..)
- 尽可能少地捕获任何字符,后跟空格,后跟文字ALL-
,后跟任意两个字符
希望这可以澄清正则表达式。如果您有任何进一步的疑问,请告诉我。
示例 Python 代码,
import re
s = '{"show permission allowed to 16": "show permission to 16\\nSchool permissions from group 17:student to group 16:teacher:\\n\\tAllow ALL-00\\nSchool permissions from group 18:library to group 16(Temp):teacher:\\n\\tNo Allow ALL-00\\nSchool permissions from group 20:Gym to group 16:teacher:\\n\\tCheck ALL-00\\nRTYAHY: FALSE\\nRTYAHY: FALSE\\n\\n#"}'
arr = re.findall(r'from group (\d+)(?:(?!Temp).)*?(Temp)?(?:(?!Temp).)*?\\t(.*? ALL-..)',s)
print(arr)
印刷,
[('17', '', 'Allow ALL-00'), ('18', 'Temp', 'No Allow ALL-00'), ('20', '', 'Check ALL-00')]
编辑:仅列出不包含的元组Temp
您将需要使用此正则表达式来避免匹配匹配中包含Temp
字符串的子字符串,
from group (\d+)(?:(?!Temp).)*\\t(.*? ALL-..)
示例 Python 代码,
import re
str1 = '{"show permission allowed to 16": "show permission to 16\\nSchool permissions from group 17:student to group 16:teacher:\\n\\tAllow ALL-00\\nSchool permissions from group 18:library to group 16(Temp):teacher:\\n\\tNo Allow ALL-00\\nSchool permissions from group 20:Gym to group 16:teacher:\\n\\tCheck ALL-00\\nRTYAHY: FALSE\\nRTYAHY: FALSE\\n\\n#"}'
arr = re.findall(r'from group (\d+)(?:(?!Temp).)*\\t(.*? ALL-..)',str1)
print(arr)
印刷,
[('17', 'Allow ALL-00'), ('20', 'Check ALL-00')]
其中不包含具有的元组Temp
推荐阅读
- javascript - 在 Reat js 中使用来自状态的验证时无法修改文本字段
- gnuplot - Gnuplot:如何将 pm3d 绘图继续到设定范围之外?
- c# - 如何在 C# 中从 SQL 中查询数据以在 chartJS 中进行可视化?
- java - 此 if 语句中的比较逻辑
- c# - DataGrid 列标题未正确填充颜色 (DataGrid.ColumnHeaderStyle)
- c++ - 将 image_ptr 转换为 Mat 容器
- javascript - 从 php 服务器获取 formdata 响应
- c# - 激活 isTrigger 后,PolygonCollider2d 不再与 CircleCollider2d 发生碰撞
- insomnia - Insomnia Rest Client - 从具有多个值的响应中获取标头
- python-3.x - 从身份验证代码在 token.pickle 中创建和存储 Google 凭据