【问题标题】:regular expression to match optional characters匹配可选字符的正则表达式
【发布时间】:2020-09-15 13:13:40
【问题描述】:

我正在努力寻找匹配以下 2 种格式的正则表达式:

cmd1 = "cmd:ifconfig:"PASS":"Fail":4:2"

cmd2 = "cmd:ifconfig:"PASS""

以下是我的示例 python 代码

import re
cmd_reg = r'cmd:(.*):\"(.*?)\"$'
result=re.findall(cmd_reg,cmd2)
print(result)      # output -> [('ifconfig', 'PASS')] Expectation [('ifconfig', 'PASS', 'FAIL', 4, 2)]
result=re.findall(cmd_reg,cmd1)
print(result)      # output -> [] Expectation :  [('ifconfig', 'PASS', '','','')]

但我无法弄清楚给出期望中提到的输出的正则表达式

【问题讨论】:

  • o/p 是什么?
  • 类似r'cmd:([^:]*):"([^"]*)"(?::"[^"]*":(\d+):")?$'?见regex101.com/r/woD4dU/1
  • 我已经更新了我指的是 o/p 而不是我更新的输出

标签: python python-3.x regex python-re


【解决方案1】:

Python 的正则表达式包无法匹配给定组的多次出现,因此这基本上不适用于单个正则表达式(其他一些正则表达式实现确实支持这一点,通过区分匹配和捕获)。

我相信你最好的选择是

  1. 匹配整体表达式并捕获命令和余数,然后
  2. 使用第二个正则表达式遍历其余组。
cmd_pattern = r'^cmd:([^:]+):(.*)$'
group_pattern = r'"?([^:"]+)"?' # or, simpler, r'[^:]+'; to retain quotes.

cmd, groups = re.match(cmd_pattern, cmd1).groups()
parsed_groups = re.findall(group_pattern, groups)

对于cmd2parsed_groups 将是['PASS'],我认为这比您想要的结果更普遍。如果您需要使用空元素填充列表,则需要手动执行此操作。


作为替代方案,您可以对这四个组进行硬编码,并将它们设为可选:

cmd_pattern = r'^cmd:([^:]+):([^:]+)(?::([^:]+))?(?::([^:]+))?(?::([^:]+))?'
re.match(cmd_pattern, cmd1).groups()
# ('ifconfig', '"PASS"', '"Fail"', '4', '2')

re.match(cmd_pattern, cmd2).groups()
# ('ifconfig', '"PASS"', None, None, None)

……我不推荐这个。而且这个复杂的表达式甚至还不能处理可选引号,这会使其更加复杂。

【讨论】:

    【解决方案2】:

    通常有很多方法可以实现这一点。如果您将给出其他示例,则正则表达式可能更适合一般情况(并且不会过度适合此示例)。 我像你一样搜索,并试图搜索:的2个分隔符之间的任何数字,这些数字在"的2次之后,所有这些额外的字符串都是可选的) 试试这个:

    cmd1 = 'cmd:ifconfig:"PASS":"":4:'
    
    cmd2 = 'cmd:ifconfig:"PASS"'
    
    import re
    cmd_reg = r'cmd:(.*):\"(.*)(:\"\":(\d):)?$'
    result=re.findall(cmd_reg,cmd2)
    print(result)
    #output -> [('ifconfig', 'PASS')]
    result=re.findall(cmd_reg,cmd1)
    print(result)
    #output -> []
    

    输出:

    [('ifconfig', 'PASS"', '', '')]
    [('ifconfig:"PASS"', '":4:', '', '')]
    

    【讨论】:

      【解决方案3】:
      cmd1 = 'cmd:ifconfig:"PASS":"":4:'
      
      cmd2 = 'cmd:ifconfig:"PASS"'
      
      import re
      cmd_reg = r'cmd:(.*):\"(.*)(:\"\":(\d):)?$'
      results =re.findall(cmd_reg,str([cmd1,cmd2])
      print(results)
      

      【讨论】:

        【解决方案4】:

        我建议以下模式:

        :(\w*):"?(\w*)"?:?"?(\w*)"?:?"?(\w*)"?:?"?(\w*)"?
        

        您可以在以下网站以交互方式尝试上述模式:

        https://regex101.com/r/M9bf6m/2

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-29
          • 1970-01-01
          相关资源
          最近更新 更多