使用正则表达式验证用户输入
Validating user input with regex
我对正则表达式的经验非常有限,所以我希望有人能帮助我。
我正在制作一个 Python 3 游戏,它的棋盘是矩形网格。我正在尝试为用户提供一种方法,可以将以下形式的多个板坐标一次输入到一个名为 coords
:
的字符串中
(x1, y1), (x2, y2), (x3, y3), ... (xn, yn)
我希望输出是一个名为 cells
的元组列表,格式类似:
[(x1, y1), (x2, y2), (x3, y3), ... (xn, yn)]
所以基本上我想模仿如何用Python代码编写元组。
现在我正在使用:
cells = [tuple(coords[i.find('(') + 1: i.rfind(')')].split(',')) for i in coords.split()]
为 (1,2) (3,4) (5,6)
形式的输入生成所需的结果,输入的元组内部和元组之间没有空格。但是,这会中断不完全遵循该形式的输入,并且不会检查有效输入。对于 cells
、 中元组中的每个 x 和 y 值,我需要验证:
- 类型(y 值)== 类型(x 值)== int
- 0 <= y 值 < game_board.height
- 0 <= x 值 < game_board.width
理想情况下,如果用户输入多个有效坐标和一些无效坐标,则有效元组将添加到 cells
并且用户将收到一条消息,如 "The following coordinates were invalid: (x1, y1), ..."
.
我知道我可以用一团糟的循环和流量控制来完成这一切,但是有没有更Pythonic的方法来用正则表达式完成这个?
编辑: 拼写
Regex 用于测试整体结构 - 剩下的就完成了 w/o regex:
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。
我对正则表达式的经验非常有限,所以我希望有人能帮助我。
我正在制作一个 Python 3 游戏,它的棋盘是矩形网格。我正在尝试为用户提供一种方法,可以将以下形式的多个板坐标一次输入到一个名为 coords
:
(x1, y1), (x2, y2), (x3, y3), ... (xn, yn)
我希望输出是一个名为 cells
的元组列表,格式类似:
[(x1, y1), (x2, y2), (x3, y3), ... (xn, yn)]
所以基本上我想模仿如何用Python代码编写元组。
现在我正在使用:
cells = [tuple(coords[i.find('(') + 1: i.rfind(')')].split(',')) for i in coords.split()]
为 (1,2) (3,4) (5,6)
形式的输入生成所需的结果,输入的元组内部和元组之间没有空格。但是,这会中断不完全遵循该形式的输入,并且不会检查有效输入。对于 cells
、 中元组中的每个 x 和 y 值,我需要验证:
- 类型(y 值)== 类型(x 值)== int
- 0 <= y 值 < game_board.height
- 0 <= x 值 < game_board.width
理想情况下,如果用户输入多个有效坐标和一些无效坐标,则有效元组将添加到 cells
并且用户将收到一条消息,如 "The following coordinates were invalid: (x1, y1), ..."
.
我知道我可以用一团糟的循环和流量控制来完成这一切,但是有没有更Pythonic的方法来用正则表达式完成这个?
编辑: 拼写
Regex 用于测试整体结构 - 剩下的就完成了 w/o regex:
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。