首页 文章

使用正则表达式验证用户输入

提问于
浏览
2

我对正则表达式的经验非常有限,所以我希望有人可以帮助我 .

我试图让用户以下面的形式一次输入几个电路板坐标到一个名为 coords 的字符串中:

(x1, y1), (x2, y2), (x3, y3), ... (xn, yn)

我希望输出是一个类似形式的名为 cells 的元组列表:

[(x1, y1), (x2, y2), (x3, y3), ... (xn, yn)]

基本上 I want to mimic how tuples can be written in Python code.

现在我正在使用:

cells = [tuple(coords[i.find('(') + 1: i.rfind(')')].split(',')) for i in coords.split()]

它以 (1,2) (3,4) (5,6) 形式为输入产生所需的结果,输入的元组内没有空格,元组之间没有空格 . 但是,对于不完全遵循该形式的输入,这会中断,并且它不会检查有效输入 . 对于 cells 中元组中的每个x和y值, I need to validate

  • type(y-value)== type(x-value)== int

  • 0 <= y-value <game_board.height

  • 0 <= x-value <game_board.width

理想情况下,如果用户输入多个有效坐标和一些无效坐标,则有效元组将添加到 cells ,并且将为用户提供类似 "The following coordinates were invalid: (x1, y1), ..." 的消息 .

我知道我可以通过乱七八糟的循环和流量控制完成所有这些,但 is there a more Pythonic way to accomplish this with regex

Edit: 拼写

1 回答

  • 2

    正则表达式用于测试整体结构 - 其余部分是用正则表达式完成的:

    inp = "(3, 4), (a, 7), (-3, 3), (3, 3)"
    
    def MaybeInt(n):
        """Returns an int if possible, else the original value."""
        try:
            return int(n)
        except:
            return n
    
    def inX(n):
        """True if inside X of board."""
        return 0<=n<5
    
    def inY(n):
        """True if inside Y of board."""
        return 0<=n<5
    
    def structOk(t):
        import re
        return re.match(r'^\s*([^,]+,[^,]+\)\s*(?:,\s*\([^,]+,[^,]+\))*)\s*$',t)
    
    def validate(t):
        t = t.replace(" ","")
        if not structOk(t):
            raise ValueError("Structually unsound - try again: "+t)
    
        k = [ x.lstrip("(") for x in t.replace(" ","").rstrip(")").split("),")]
        tups = [ tuple(map(MaybeInt,tu.split(","))) for tu in k]
    
        # our "decider" for whats valid/invalid which is used to divide the tuples
        # into our valid/invalid return list's
        test = lambda q: all(isinstance(num,int) for num in q) and inX(q[0]) and inY(q[1])
    
    
        rv = [[],[]]  # prepare and append by our decider test
        for k in tups:
            # True == 1, False == 0
            rv[1-test(k)].append(k)
    
        return rv
    
    valid, invalid = validate(inp)
    
    print(valid)
    print(invalid)
    

    输出:

    [(3, 4), (3, 3)]    # valid
    [('a', 7), (-3, 3)] # invalid
    

    有关正则表达式和详细说明,请参阅https://regex101.com/r/OrHGaR/1 .

    简短描述:它寻找(......,...)......不是, - 你可以通过使用f.e来改进它 . [1234567890a-zA-Z] 而不是 [^,] 但随后它会更快地转到ValueError .

相关问题