小编典典

在Python中,如何查询符合特定查询条件的单词列表?

python

查询条件应支持布尔运算符和正则表达式。我已经读过关于Booleano的文章,但是它不支持正则表达式。

如果没有满足此要求的东西,那将是开始构建的最佳技术?

以下示例中的语法只是一个示例,但是它提供的功能应该存在。

is True if ('client/.+' and 'user_a') but (not 'limited' unless ('.+special' or 'godmode'))

等于

is True if 'client/.+' and 'user_a' and (not ('limited' and (not ('.+special' or 'godmode'))))

适用于以下清单

is_true  = ['client/chat', 'user_a', 'limited', 'extraspecial']
is_false = ['client/ping', 'user_a', 'limited']
is_false = ['server/chat']
is_false = ['server/ping', 'ping']

阅读 209

收藏
2021-01-20

共1个答案

小编典典

我设法使用pyparsing模块解决了这个问题。

import re
import pyparsing

class BoolRegEx(object):

  def Match(self, tags=[], query=""):
    self.tags = tags
    if ' ' not in query:
      return self.Search(query)
    else:
      return pyparsing.operatorPrecedence(
        pyparsing.Word(pyparsing.printables, excludeChars="()"), [
          (pyparsing.Literal("NOT"), 1, pyparsing.opAssoc.RIGHT, self.Not),
          (pyparsing.Literal("OR"),  2, pyparsing.opAssoc.LEFT,  self.Or),
          (pyparsing.Literal("AND"), 2, pyparsing.opAssoc.LEFT,  self.And),
        ]
      ).parseString(query, parseAll=True)[0]

  def Search(self, a):
    try:
      regex = re.compile(a.replace("<<", "#~").replace(">>", "~#").replace(">", ")").replace("<", "(").replace("#~", "<").replace("~#", ">"))
      for tag in self.tags:
        match = regex.match(tag)
        if match and len(match.group(0)) == len(tag):
          return True
      return False
    except:
      raise

  def And(self, t):
    for a in t[0][0::2]:
      if isinstance(a, basestring):
        v = self.Search(a)
      else:
        v = bool(a)
      if not v:
        return False
    return True

  def Or(self, t):
    for a in t[0][0::2]:
      if isinstance(a, basestring):
        v = self.Search(a)
      else:
        v = bool(a)
      if v:
        return True
    return False

  def Not(self, t):
    a = t[0][1]
    if isinstance(a, basestring):
      return not self.Search(a)
    else:
      return not bool(a)

print BoolRegEx().Match(['client/chat', 'user_a', 'limited', 'extraspecial'], "client/.+ AND user_a AND NOT ( limited AND NOT ( .+<r|i>special OR godmode ) )")
# False

print BoolRegEx().Match(['client/chat', 'user_a', 'limited', 'superspecial'], "client/.+ AND user_a AND NOT ( limited AND NOT ( .+<r|i>special OR godmode ) )")
# True

为了避免发生冲突,我必须用<>替换regexp(),但是目前所有这些似乎都是最好的解决方案。

2021-01-20