我有以下字符串:
2020-10-2125Chavez and Sons
2020-05-02Bean Inc
NaNRobinson, Mcmahon and Atkins
2020-04-25Hill-Fisher
2020-04-02Nothing and Sons
52457Carpenter and Sons
0Carpenter and Sons
Carpenter and Sons
NoneEconomy and Sons
2020-04-02
我想把它分开:
myRegex = '^([-d]{0,}|[NnaAOoEe]{0,})(.*)' or '^([0-9]{4}-[0-9]{2}-[0-9]{2,}|[d]{0,}|[NnaAOoEe]{0,})([D]{0,})$'
我想要所有的数字,精确匹配(na,nan,none(-大小写和""在第一组中,如:
[2020-10-2125][Chavez and Sons]
[2020-05-02][Bean Inc]
[NaN][Robinson, Mcmahon and Atkins]
[2020-04-25][Hill-Fisher]
[2020-04-02][Nothing and Sons]
[52457][Carpenter and Sons]
[0][Carpenter and Sons]
[][Carpenter and Sons]
[None][Economy and Sons]
[2020-04-02][]
这是错误的:
[2020-04-02No][thing and Sons]
我想要
[2020-04-02][Nothing and Sons]
如何编写一个正则表达式来检查精确匹配,如"none"-不区分大小写(还应识别"none"、"One"等(?
https://regex101.com/r/HvnZ47/3
关于re.I的以下内容如何:
(None|NaN?|[-d]+)?(.*)
https://regex101.com/r/d4XPPb/3
说明:
(None|NaN?|[-d]+)?
- 非此即彼
- 或者最后一个N是可选的NaN(由于
?
(,因此它也与NA匹配 - 或数字和短划线一次或多次
- 由于
?
,整个组()
是可选的,这意味着它可能不在那里
(.*)
结尾的任意字符
但是,仍然可能存在边缘情况。考虑以下内容:
National Geographic
---Test
将被解析为
[Na][tional Geographic]
[---][Test]
替代方案:
从这里开始,我们可以继续使正则表达式更加复杂,但是,我认为在没有正则表达式的情况下实现自定义解析会简单得多。每行中的循环字符和:
- 如果它以数字开头,则将所有数字和破折号解析到第1组,其余部分解析到第2组(即,当您命中一个字符时,更改组(
- 取字符串的前4个字符,如果它们是"0";无";,把它们分开。同时确保第5个字符为大写(不区分大小写的
line[:4].lower() == "none" and line[4].isupper()
( - 类似于上述步骤,但对于NA和NaN:
line[:3].lower() == "nan" and line[3].isupper()
line[:2].lower() == "na" and line[2].isupper()
以上内容应该会产生更准确的结果,而且应该更容易阅读。
示例代码:
with open("/tmp/data") as f:
lines = f.readlines()
results = []
for line in lines:
# Remove spaces and n
line = line.strip()
if line[0].isdigit() or line[0] == "-":
i = 0
while line[i].isdigit() or line[i] == "-":
i += 1
if i == len(line) - 1:
i = len(line)
break
results.append((line[:i], line[i:]))
elif line[:4].lower() == "none" and line[4].isupper():
results.append((line[:4], line[4:]))
elif line[:3].lower() == "nan" and line[3].isupper():
results.append((line[:3], line[3:]))
elif line[:2].lower() == "na" and line[2].isupper():
results.append((line[:2], line[2:]))
else:
# Assume group1 is missing! Everything is group2
results.append((None, line))
for g1, g2 in results:
print(f"[{g1 or ''}][{g2}]")
数据:
$ cat /tmp/data
2020-10-2125Chavez and Sons
2020-05-02Bean Inc
NaNRobinson, Mcmahon and Atkins
2020-04-25Hill-Fisher
2020-04-02Nothing and Sons
52457Carpenter and Sons
0Carpenter and Sons
Carpenter and Sons
NoneEconomy and Sons
NoNeEconomy and Sons
2020-04-02
NAEconomy and Sons
---Test
National Geographic
输出:
$ python ~/tmp/so.py
[2020-10-2125][Chavez and Sons]
[2020-05-02][Bean Inc]
[NaN][Robinson, Mcmahon and Atkins]
[2020-04-25][Hill-Fisher]
[2020-04-02][Nothing and Sons]
[52457][Carpenter and Sons]
[0][Carpenter and Sons]
[][Carpenter and Sons]
[None][Economy and Sons]
[NoNe][Economy and Sons]
[2020-04-02][]
[NA][Economy and Sons]
[---][Test]
[][National Geographic]
您可以将想要匹配的表达式与简单的|
组合起来,但请记住,引擎总是倾向于第一个可能的匹配;因此,您希望将更具体的模式放在首位,然后再回到更通用的情况。
试试这个:
my_re = re.compile(r'^([0-9]{4}-[0-9]{2}-[0-9]{2,}|d+|N(?:aN|one)|)(D.*)$', re.IGNORECASE)
re.IGNORECASE
标志表示忽略大小写差异。
此外,请注意,量词{0,}
最好写成*
;但您希望至少需要一个匹配,或者返回到更通用的模式,所以实际上您需要+
(也可以写成{1,}
;但同样,更喜欢更简洁的标准表示法(。D
周围不需要方括号,因为它已经封装了一个字符类(但如果您想合并两个字符类,如[-d]
,您确实需要方括号(。
演示:https://ideone.com/Qwp5ao
最后,请注意,用于命名局部变量的标准Python表示法更喜欢snake_case
而不是dromedaryCase
。(另请参阅维基百科。(