【问题标题】:Using regex to create a list of dictionaries with positive lookbehind使用正则表达式创建具有正向回溯的字典列表
【发布时间】:2020-11-28 10:02:55
【问题描述】:

我正在尝试使用正则表达式正向查找创建字典列表。我尝试了两种不同的代码:

变体 1

string = '146.204.224.152 - lubo233'

for item in re.finditer( "(?P<host>[0-9]*[.][0-9]*[.][0-9]*[.][0-9]*)(?P<user_name>(?<= - )[a-z]*[0-9]*)", string ):
    print(item.groupdict())

变体 2

string = '146.204.224.152 - lubo233'
for item in re.finditer( "(?P<host>[0-9]*[.][0-9]*[.][0-9]*[.][0-9]*)(?<= - )(?P<user_name>[a-z]*[0-9]*)", string ):
    print(item.groupdict())

期望的输出

{'host': '146.204.224.152', 'user_name': 'lubo233'}

问题/问题

在这两种情况下,我都无法消除子字符串“-”。

使用积极的后视(?&lt;= - ) 会使我的代码出错。

谁能帮助找出我的错误?谢谢。

【问题讨论】:

    标签: python regex dictionary positive-lookbehind


    【解决方案1】:

    我建议您删除积极的lookbehind,并在每个部分之间正常放置连接字符

    还有一些改进

    • \. 而不是[.]

    • [0-9]{,3} 而不是[0-9]*

    • (?:\.[0-9]{,3}){3} 而不是\.[0-9]{,3}\.[0-9]{,3}\.[0-9]{,3}

    添加.*- 以处理可能存在的任何单词

    rgx = re.compile(r"(?P<host>[0-9]{,3}(?:\.[0-9]{,3}){3}).* - (?P<user_name>[a-z]*[0-9]*)")
    
    vals = ['146.204.224.152 aw0123 abc - lubo233',
            '146.204.224.152 as003443af - lubo233',
            '146.204.224.152 - lubo233']
    
    for val in vals:
        for item in rgx.finditer(val):
            print(item.groupdict())
    
    # Gives
    {'host': '146.204.224.152', 'user_name': 'lubo233'}
    {'host': '146.204.224.152', 'user_name': 'lubo233'}
    {'host': '146.204.224.152', 'user_name': 'lubo233'}
    

    【讨论】:

    • 我明白你的意思。但是当两个子字符串之间的字符长度未知时会发生什么:'146.204.224.152'和'-lubo233'?示例:字符串 = '146.204.224.152 aw0123 abc - lubo233' 或字符串 = '146.204.224.152 as003443af - lubo233'
    • @KaneChew 请编辑您的初始帖子以添加几个输入字符串示例。此外,我的代码与您的代码及其工作方式相同,您的初始代码在中间没有处理可能的不同内容;)
    【解决方案2】:

    正向后视不起作用的原因是您正在尝试匹配:

    • (?P&lt;host&gt;[0-9]*[.][0-9]*[.][0-9]*[.][0-9]*) IP 地址
    • 立即后跟 用户名模式(?P&lt;user_name&gt;(?&lt;= - )[a-z]*[0-9]*) 前面应该是 (?&lt;= - )

    因此,一旦正则表达式引擎使用了 IP 地址 模式,您就告诉它应该匹配前面有 (?&lt;= - )用户名模式,但前面的是 IP 地址 模式。换句话说,一旦 IP 模式 被匹配,剩下的字符串就是:

    - lubo233
    

    应该立即匹配的模式,如re.match,是:

    (?P<user_name>(?<= - )[a-z]*[0-9]*) 
    

    这显然不匹配。为了说明我的观点,请查看此模式是否有效:

    import re
    
    string = '146.204.224.152 - lubo233'
    for item in re.finditer(r"((?P<host>[0-9]*[.][0-9]*[.][0-9]*[.][0-9]*)( - ))(?P<user_name>(?<= - )[a-z]*[0-9]*)", string):
        print(item.groupdict())
    

    输出

    {'host': '146.204.224.152', 'user_name': 'lubo233'}
    

    如果您需要在两个模式之间匹配任意数量的字符,您可以这样做:

    import re
    
    string = '146.204.224.152 adfadfa - lubo233'
    for item in re.finditer(r"((?P<host>\d{3,}[.]\d{3,}[.]\d{3,})(.* - ))(?P<user_name>(?<= - )[a-z]*[0-9]*)", string):
        print(item.groupdict())
    

    输出

    {'host': '146.204.224', 'user_name': 'lubo233'}
    

    【讨论】:

    • 按照您的思路,“一旦正则表达式引擎消耗了 IP 地址模式”,就会留下以下子字符串:“-lubo233”。在这种情况下,“ - ”不是在user_name之前吗?还是我没有正确理解正则表达式?
    • @KaneChew positive lookbehind 不使用字符串。正如你所说,左边的字符串是“ - lubo233”,你告诉它,它应该以“ - ”开头。
    猜你喜欢
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    • 2012-12-06
    • 1970-01-01
    相关资源
    最近更新 更多