我如何编写 Python 正则表达式,它需要 4 个数字后跟拼音字母值?示例:1 2 3 4 阿尔法布拉沃 -> 1234AB

How can I write Python Regex that will take 4 numbers followed by Phonetic Alphabet values? Example: 1 2 3 4 Alpha Bravo -> 1234AB

我正在使用以下脚本,以便 Rasa 框架在用户传递荷兰邮政编码时检测到它:

https://medium.com/@naoko.reeves/rasa-regex-entity-extraction-317f047b28b6

荷兰邮政编码的格式是 1234 AB。这在使用像这样的正则表达式时效果很好:

 [1-9][0-9]{3}[\s]?[a-z]{2}

但是,我现在正在尝试实现语音转文本功能(Azure 认知服务),该功能不太容易识别字母表。例如 'B' 被选为 'Bee'.

我现在正在尝试更改正则表达式,以便用户可以说“1 2 3 4 Alpha Bravo”,然后正则表达式提取器将挑选出“1 2 3 4 A B”。

我试过像下面这样使用单词边界:

[1-9]*[\s]?[0-9]*[\s]?[0-9]*[\s]?[0-9]*[\s]?\b[a-zA-Z]

[1-9]\s[0-9\s]{5}\s?\b[a-zA-Z]

前者过于宽松,如果用户说 'Hello There',它将触发正则表达式提取器并将 'HT' 传递给邮政编码行为。

后者更严格,但我只能将 '1 2 3 4 Alpha Bravo' 匹配为 '1 2 3 4 A'。

对于解决此问题的任何解决方案,我将不胜感激。如果这在 Regex 中不容易实现,我相信更改链接的中篇文章中的以下函数会得到我想要的结果。不幸的是,我不是 Python/Regex 专家 :)。

 def match_regex(self, message):
    extracted = []
    for d in self.regex_feature:
        match = re.search(pattern=d['pattern'], string=message)
        if match:
            entity = {
                "start": match.pos,
                "end": match.endpos,
                "value": match.group(),
                "confidence": 1.0,
                "entity": d['name'],
            }
            extracted.append(entity)
    extracted = self.add_extractor_name(extracted)
    return extracted

我希望这已经够清楚了。

谢谢!

杰克

也许你可以试试这样的正则表达式:

(?i)\b([1-9][0-9]{3} ?[a-z])[a-z]* +([a-z])[a-z]*

无论此正则表达式匹配什么,只需将其替换为 </code> 即,第 1 组的内容后跟第 2 组的内容。</p> <p><strong><a href="https://regex101.com/r/zYhc5W/1" rel="nofollow noreferrer">Click for Demo</a></strong></p> <p><strong><a href="https://regex101.com/r/zYhc5W/1/codegen?language=python" rel="nofollow noreferrer">Click for Code</a></strong></p> <p><strong>解释:</strong></p> <ul> <li><code>(?i) - 切换使匹配不区分大小写

  • \b - 单词边界
  • ([1-9][0-9]{3} ?[a-z]) - 组 1 的内容如下所述
    • [1-9] - 匹配从 1 到 9 的任何数字
    • [0-9]{3} - 匹配从 0 到 9 的任意数字出现 3 次
    • ? - 匹配 0 次或 1 次出现的 space
    • [a-z] - 匹配字母的单次出现。 这将是数字后第一个单词的第一个字母
  • [a-z]* - 匹配出现 0 次以上的字母
  • + - 匹配出现 1 次以上的 space
  • ([a-z]) - 匹配一个字母并将其存储在 组 2 中。 这将是第二个单词的第一个字母
  • [a-z]* - 匹配出现 0 次以上的字母
  • 您可以使用 3 组匹配数字之间和大写字符 A-Z 之间的可选空格。

    ([1-9](?:\s*[0-9]){3})\s?([A-Z])[a-z]*\s*([A-Z])[a-z]*
    

    模式匹配

    • ([1-9](?:\s*[0-9]){3}) 用可选的空白字符匹配 4 个数字
    • \s? 匹配一个可选的空格
    • ([A-Z])[a-z]*\s* 匹配大写字符 A-Z,后跟可选的小写字符和可选的 whitespac
    • ([A-Z])[a-z]* 匹配一个大写字符 A-Z,后跟可选的小写字符

    regex demo

    更严格的选项可以匹配大写字符 A-Z,后跟相同字符的大写或小写变体,使用可选的重复反向引用

    \b([1-9](?:\s*[0-9]){3})\s?([A-Z])(?i:*)\s*([A-Z])(?i:*)\b
    

    Regex demo | Python demo

    import re
    
    pattern = r"\b([1-9](?:\s*[0-9]){3})\s?([A-Z])(?i:*)\s*([A-Z])(?i:*)\b"
    strings = [
        "1 2 3 4 Alpha Bravo",
        "1234 Alpha Bravo",
        "1234A Bbbbbbbc",
        "1234Aaa Bbb",
        "1234Aa Bbb",
        "1234A BbbbbBbb"
    ]
    
    for s in strings:
        print(re.findall(pattern, s))
    

    输出

    []
    []
    []
    [('1234', 'A', 'B')]
    [('1234', 'A', 'B')]
    [('1234', 'A', 'B')]