我想为 python 片段创建一个正则表达式。
import re
pattern = "\d*\.?\d+[Ee]?[+-]?\d*"
r = re.compile(pattern)
txt = """
12
.12
12.5
12.5E4
12.5e4
12.4E+4
12E4
12e-4
"""
x = r.findall(txt)
print(x)
用于过滤来自 txt 的所有有效输入,此代码很好,但输入无效,例如
.12e, 12.3+4
也被允许我该如何解决这个问题?
不需要时不要使用正则表达式。让 Python 确定哪些是有效的更符合 Pythonic[tm](并且更容易、更可靠)。
results = []
for line in txt.split():
try:
float(line)
except ValueError:
pass
else:
results.append(line)
print results
我建议你使用正则表达式模式
^(?=\.?\d)\d*(?:\.\d*)?(?:[eE][+-]?\d+)?$
传统的正则表达式是这样的:
pattern = (
"(?:"
r"\d+(?:\.\d+)(:?[Ee][-+]?\d+)"
"|"
r"\.\d+(:?[Ee][+-]?\d+)"
")"
)
但是你总是可以用简单的方法做事:
def is_number(x):
try:
float(x)
return True
except ValueError:
return False
你可以试试:\d*\.?\d+(?:[Ee][+-]?\d+)?$。这将指数部分标记为一个组。我还添加了一个$以确保它与字符串的结尾匹配。
此外,由于您的正则表达式包含\,因此您应该使用原始字符串文字,例如:r'\n',它是文字\n,而不是换行符。
更简单的方法是使用float()并检查ValueError异常。
尝试将您的正则表达式更改为以下内容:
\d*\.?\d+(?:[Ee][+-]?\d+)?
这使得如果eorE存在,则始终至少有一个数字,因此+and-仅当它们跟随eor时才有效E。
请注意,您应该使用原始字符串文字来确保正确转义反斜杠(特别不会影响此字符串,但如果您尝试\b在正则表达式中使用类似的东西,您会看到不同之处):
pattern = r"\d*\.?\d+(?:[Ee][+-]?\d+)?"
你在这里,可能是最简单的:
^(\d*\.?\d+([Ee][+-]?\d+)?)$
将 ^ 和 $ 替换为您想要的分隔符,空格或其他内容。
解决方案说明:
您的解决方案
\d*\.?\d+[Ee]?[+-]?\d*
允许 E 放置不带数字 -> 因此 \d+ 在我的末尾。我还制作了 E 和可选的 +/-,然后是单个组中的强制数字(即,将其全部括在括号中),因此它们不能没有彼此而存在。整个组 ([Ee][+-]?\d+) 是可选的 (?) 以适应没有该符号的数字示例。
或者,避免一起使用正则表达式,使用 Python 标记器来查找它们:
test2.txt
一些颠簸
2.34
1.7e2
一些颠簸
示例代码
from tokenize import generate_tokens, NUMBER
source = open('test2.txt').readline
numbers = [ (val, eval(val)) for typ, val, _, _, _ in generate_tokens(source) if typ==NUMBER]
print numbers
# [('2.34', 2.34), ('1.7e2', 170.0)]
这样的事情应该这样做(未经测试):
"\d*\.?\d+(?:[Ee][+-]\d)?\d*"