Python 如何将缩写与其含义与正则表达式匹配?

Python 如何将缩写与其含义与正则表达式匹配?,python,regex,regex-lookarounds,Python,Regex,Regex Lookarounds,我正在寻找与以下字符串匹配的正则表达式模式: 一些示例文本(集合)演示了我要查找的内容。能源系统模型(ESM)用于寻找特定的优化(SCO)。有人说计算机系统(CUST)很酷。夏季最好在户外(出局)打球 我的目标是满足以下条件: Some example text (SET) Energy system models (ESM) specific optima (SCO) computer systems (CUST) outside (OUTS) 重要的是,这并不总是三个词和它们的第一个字母。

我正在寻找与以下字符串匹配的正则表达式模式:

一些示例文本(集合)演示了我要查找的内容。能源系统模型(ESM)用于寻找特定的优化(SCO)。有人说计算机系统(CUST)很酷。夏季最好在户外(出局)打球

我的目标是满足以下条件:

Some example text (SET)
Energy system models (ESM)
specific optima (SCO)
computer systems (CUST)
outside (OUTS)
重要的是,这并不总是三个词和它们的第一个字母。有时缩写词的字母仅包含在前面的单词中。这就是为什么我开始研究
正向查找
。但是,它受到长度的限制,可以通过将其与正向前瞻相结合来解决。不过,到目前为止,我还没有想出一个可靠的解决方案

到目前为止我所尝试的:

(\b[\w -]+?)\((([A-Z])(?<=(?=.*?\3))(?:[A-Z]){1,4})\)
我还尝试在第一组开头引用缩写的第一个字母。但那根本不起作用

我看过但没有发现有用的东西:

有用资源:

    • 我建议使用

      import re
      def contains_abbrev(abbrev, text):
          text = text.lower()
          if not abbrev.isupper():
              return False
          cnt = 0
          for c in abbrev.lower():
              if text.find(c) > -1:
                  text = text[text.find(c):]
                  cnt += 1
                  continue
          return cnt == len(abbrev)
       
      text= "Some example text (SET) that demonstrates what I'm looking for. Energy system models (ESM) are used to find specific optima (SCO). Some say computer systems (CUST) are cool. In the summer playing outside (OUTS) should be preferred. Stupid example(s) Stupid example(S) Not stupid example (NSEMPLE), bad example (Bexle)"
      abbrev_rx = r'\b(([A-Z])\w*(?:\s+\w+)*?)\s*\((\2[A-Z]*)\)'
      print( [x.group() for x in re.finditer(abbrev_rx, text, re.I) if contains_abbrev(x.group(3), x.group(1))] )
      

      使用的正则表达式是

      (?i)\b(([A-Z])\w*(?:\s+\w+)*?)\s*\((\2[A-Z]*)\)
      
      看。详情:

      • \b
        -单词边界
      • ([A-Z])\w*(?:\s+\w+*?)
        -第1组(
        文本)
        ):将ASCII字母捕获到第2组中,然后0+字字符后跟0或更多出现的1+空格,后跟1+字字符,尽可能少
      • \s*
        -0+空格
      • \(
        -a
        字符
      • (\2[A-Z]*)
        -第3组(
        abbrev
        ):与第2组中的值相同,然后是0个或更多ASCII字母
      • \)
        -a
        字符

      一旦有匹配项,第3组作为
      abbrev
      传递,第1组作为
      text
      传递给
      contains_abbrev(abbrev,text)
      方法,该方法确保
      abbrev
      是大写字符串,
      abbrev
      中的字符顺序与
      text
      中的字符顺序相同,并且都出现在
      文本中

      仅仅正则表达式是不够的。。看起来您可能需要一个用于此的python脚本。。。 这将处理您的所有场景:

      import re
      a="Some example text (SET) that demonstrates what I'm looking for. Energy system models (ESM) are used to find specific optima (SCO). Some say computer systems (CUST) are cool. In the summer playing outside (OUTS) should be preferred.";
      b=re.findall("(\((.*?)\))",a)
      a=a.replace(".","")
      i=a.split(' ')
      for c in b:
         cont=0
         m=[]
         s=i.index(c[0])
         l=len(c[1])
         al=s-l
         for j in range(al,s+1):
             if i[j][0].lower() == c[1][0].lower():
                  cont=1
             if cont == 1:
                  m.append(i[j])
         print(' '.join(m))
      
      输出:

      一些示例文本(集合)

      能源系统模型(ESM)

      特定优化(SCO)

      计算机系统(CUST)


      外部(OUTS)

      没有逻辑将括号之间的大写字符连接到它前面的单词,对吗?请尝试
      [x.group(),在re.finditer(r'\b([A-Z])\w*(?:\s+\w+*?\s*\(\1[A-Z]*\),text)]
      ()。第四个逻辑是,它预先对单词进行了一些缩写,因此大写字符必须包含在其中。啊,它必须是
      [x.group(),对于re.finditer(r'\b([A-Z])\w*(?:\s+\w+*?\s*(\1[A-Z]*\),text,re.I)]
      ()。我不确定只检查第一个单词的首字母是否可以。大卫,这足够好吗?或者你认为一定有更复杂的逻辑吗?@WiktorStribiżew这似乎不太正确,因为缩写应该都是大写的。否则,可能会出现如下情况的误报:
      愚蠢的示例
      中包含的
      文本
      应转换为小写,并且正则表达式的缩写部分应具有固定长度
      {2,}
      。通过这些更改,它可以按预期工作。@david不需要小写,
      re.I
      使模式不区分大小写。如果需要确保缩写中至少有2个字符,请将
      \2[A-Z]*
      替换为
      \2[A-Z]+
      。需要使用小写,因为用于比较的文本不一定是小写的。因此,到目前为止,您的代码在第一个缩写中失败。@david我现在明白您的意思了。我添加了
      文本
      小写行。
      import re
      a="Some example text (SET) that demonstrates what I'm looking for. Energy system models (ESM) are used to find specific optima (SCO). Some say computer systems (CUST) are cool. In the summer playing outside (OUTS) should be preferred.";
      b=re.findall("(\((.*?)\))",a)
      a=a.replace(".","")
      i=a.split(' ')
      for c in b:
         cont=0
         m=[]
         s=i.index(c[0])
         l=len(c[1])
         al=s-l
         for j in range(al,s+1):
             if i[j][0].lower() == c[1][0].lower():
                  cont=1
             if cont == 1:
                  m.append(i[j])
         print(' '.join(m))