代码之家  ›  专栏  ›  技术社区  ›  mlissner

用于查找有效sphinx字段的正则表达式

  •  2
  • mlissner  · 技术社区  · 16 年前

    我试图验证给斯芬克斯的字段是否有效,但我遇到了困难。

    假设有效字段是cat、mouse、dog、puppy。

    有效搜索将是:

    • @(cat)搜索词
    • @(猫,狗)搜索词
    • @cat searchterm1@狗searchterm2
    • @(猫,狗)searchterm1@鼠标searchterm2

    因此,查询如下: @(山羊)

    我得到了一些简单的查询,比如@cat和这个正则表达式:(?:@)([^(]*)

    但我不知道怎么找到剩下的。

    我正在使用python&django,不管这值多少钱。

    6 回复  |  直到 16 年前
        1
  •  3
  •   Tomalak    16 年前

    为了匹配所有允许的字段,以下看起来相当可怕的regex可以工作:

    @((?:cat|mouse|dog|puppy)\b|\((?:(?:cat|mouse|dog|puppy)(?:, *|(?=\))))+\))
    

    它按顺序返回这些匹配项: @cat , @(cat) @(cat, dog) , @猫 @dog , @(猫,狗) @mouse .

    @                               # the literal character "@"
    (                               # match group 1
      (?:cat|mouse|dog|puppy)       #  one of your valid search terms (not captured)
      \b                            #  a word boundary
      |                             #  or...
      \(                            #  a literal opening paren
      (?:                           #  non-capturing group
        (?:cat|mouse|dog|puppy)     #   one of your valid search terms (not captured)
        (?:                         #   non-capturing group
          , *                       #    a comma "," plus any number of spaces
          |                         #    or...
          (?=\))                    #    a position followed by a closing paren
        )                           #   end non-capture group
      )+                            #  end non-capture group, repeat
      \)                            #  a literal closing paren
    )                               # end match group one.
    

    现在要确定 无效

    @(?!(?:cat|mouse|dog|puppy)\b|\((?:(?:cat|mouse|dog|puppy)(?:, *|(?=\))))+\))
    --^^
    

    这将确定任何 @ 在其之后尝试使用无效搜索项(或项组合)的字符。修改它使它 比赛

    你得做好准备 (?:cat|mouse|dog|puppy) 并将其插入regex的静态其余部分。也不应该太难做到。

        2
  •  2
  •   PaulMcG    16 年前

    from pyparsing import *
    
    # define the pattern of a tag, setting internal results names for easy validation
    AT,LPAR,RPAR = map(Suppress,"@()")
    term = Word(alphas,alphanums).setResultsName("terms",listAllMatches=True)
    sphxTerm = AT + ~White() + ( term | LPAR + delimitedList(term) + RPAR )
    
    # define tags we consider to be valid
    valid = set("cat mouse dog".split())
    
    # define a parse action to filter out valid terms, and attach to the sphxTerm
    def filterValid(tokens):
        tokens = [t for t in tokens.terms if t not in valid]
        if not(tokens):
            raise ParseException("",0,"")
        return tokens
    sphxTerm.setParseAction(filterValid)
    
    
    ##### Test out the parser #####
    
    test = """@cat search terms @ house
        @(cat) search terms 
        @(cat, dog) search term @(goat)
        @cat searchterm1 @dog searchterm2 @(cat, doggerel)
        @(cat, dog) searchterm1 @mouse searchterm2 
        @caterpillar"""
    
    # scan for invalid terms, and print out the terms and their locations
    for t,s,e in sphxTerm.scanString(test):
        print "Terms:%s Line: %d Col: %d" % (t, lineno(s, test), col(s, test))
        print line(s, test)
        print " "*(col(s,test)-1)+"^"
        print
    

    有了这些可爱的结果:

    Terms:['goat'] Line: 3 Col: 29
        @(cat, dog) search term @(goat)
                                ^
    
    Terms:['doggerel'] Line: 4 Col: 39
        @cat searchterm1 @dog searchterm2 @(cat, doggerel)
                                          ^
    
    Terms:['caterpillar'] Line: 6 Col: 5
        @caterpillar
        ^
    

    最后一段代码将为您完成所有扫描,并为您提供找到的无效标记列表:

    # print out all of the found invalid terms
    print list(set(sum(sphxTerm.searchString(test), ParseResults([]))))
    

    ['caterpillar', 'goat', 'doggerel']
    
        3
  •  1
  •   Tim Pietzcker    16 年前

    这应该起作用:

    @\((cat|dog|mouse|puppy)\b(,\s*(cat|dog|mouse|puppy)\b)*\)|@(cat|dog|mouse|puppy)\b
    

    它要么匹配一个 @parameter 或者是带圆括号的 @(par1, par2)

    它还确保不接受部分匹配( @caterpillar ).

        4
  •  0
  •   Alan Moore Chris Ballance    16 年前

    field_re = re.compile(r"@(?:([^()\s]+)|\([^()]+\))")
    

    单个字段名(如 cat 在里面 @cat @(cat, dog) 将存储在第2组中。在后一种情况下,您需要使用 split() 或者别的什么;用Python正则表达式无法单独捕获名称。

        5
  •  0
  •   thetaiko    16 年前

    import re
    sphinx_term = "@goat some words to search"
    regex = re.compile("@\(?(cat|dog|mouse|puppy)(, ?(cat|dog|mouse|puppy))*\)? ")
    if regex.search(sphinx_term):
        send the query to sphinx...
    
        6
  •  0
  •   mlissner    16 年前

    我最终以不同的方式做了这件事,因为以上都不起作用。首先我找到了像@cat这样的字段:

    attributes = re.findall('(?:@)([^\( ]*)', query)
    

    regex0 = re.compile('''
        @               # at sign
        (?:             # start non-capturing group
            \w+             # non-whitespace, one or more
            \b              # a boundary character (i.e. no more \w)
            |               # OR
            (               # capturing group
                \(              # left paren
                [^@(),]+        # not an @(),
                (?:                 # another non-caputing group
                    , *             # a comma, then some spaces
                    [^@(),]+        # not @(),
                )*              # some quantity of this non-capturing group
                \)              # a right paren
            )               # end of non-capuring group
        )           # end of non-capturing group
        ''', re.VERBOSE)
    
    # and this puts them into the attributes list.
    groupedAttributes = re.findall(regex0, query)
    for item in groupedAttributes:
        attributes.extend(item.strip("(").strip(")").split(", "))
    

    接下来,我检查找到的属性是否有效,并添加它们(唯一地添加到数组中):

    # check if the values are valid.
    validRegex = re.compile(r'^mice$|^mouse$|^cat$|^dog$')
    
    # if they aren't add them to a new list.
    badAttrs = []
    for attribute in attributes:
        if len(attribute) == 0:
            # if it's a zero length attribute, we punt
            continue
        if validRegex.search(attribute.lower()) == None:
            # if the attribute from the search isn't in the valid list
            if attribute not in badAttrs:
                # and the attribute isn't already in the list
                badAttrs.append(attribute)