Python中的正则表达式:如何进行非匹配
我直接说吧:我有一个像这样的字符串(但有成千上万行)
Ach-emos_2
Ach. emos_54
Achėmos_18
Ąžuolas_4
Somtehing else_2
我需要删除那些不符合 a-z
和 ąčęėįšųūž
以及 _
和 任何整数
的行(第三和第四行符合这个条件)。而且这个匹配应该不区分大小写。我觉得正则表达式应该是
[a-ząčęėįšųūž]+_\d+ #don't know where to put case insensitive modifier
但是,匹配那些不是字母(包括立陶宛字母)加下划线加整数的行的正则表达式应该是什么样的呢?我试过
re.sub(r'[^a-ząčęėįšųūž]+_\d+\n', '', words)
但是效果不好。
提前谢谢你,如果我的英语不太好,抱歉。
3 个回答
不太清楚Python是怎么处理修饰符的,但如果你想要直接在原来的内容上进行修改,可以用类似下面的方式(不区分大小写):
注意:这些字符中有些是utf8格式的。如果你想用字面上的表示方式,你的编辑器和编程语言必须支持这个格式,否则建议使用 \u.. 代码来表示字符。
s/(?i)^(?![a-ząčęėįšųūž]+_\d+(?:\n|$)).*(?:\n|$)//mg;
这里的正则表达式是:r'(?i)^(?![a-ząčęėįšųūž]+_\d+(?:\n|$)).*(?:\n|$)'
替换的内容是 ''
修饰符是多行和全局的。
简单解释一下:修饰符是全局的,并且支持多行。
(?i) // case insensitive flag
^ // start of line
(?![a-ząčęėįšųūž]+_\d+(?:\n|$)) // look ahead, not this form of a line ?
.* // ok then select all except newline or eos
(?:\n|$) // select newline or end of string
首先,根据你给出的例子,每一行的结尾都是下划线加上数字,所以你只需要反转原来的匹配方式。如果这个例子不太代表真实情况,那么反转匹配可能会得到这样的结果:
abcdefg_nodigitshere
但你可以通过这种方式进行进一步筛选:
import re
mydigre = re.compile(r'_\d+$')
myreg = re.compile(r'^[a-ząčęėįšųūž]+_\d+$', re.I)
for line in inputs.splitlines():
if re.match(myreg, line):
# do x
elif re.match(mydigre, line):
# do y
else:
# line doesn't end with _\d+
另一个选择是使用Python的集合。这种方法只有在你的每一行都是独一无二的(或者你不介意去掉重复的行)并且不在乎顺序的时候才有意义。它可能会占用比较多的内存,但速度可能会很快。
all_lines = set([line for line in inputs.splitlines()])
alpha_lines = set([line for line in all_lines if re.match(myreg, line)])
nonalpha_lines = all_lines - alpha_lines
nonalpha_digi_lines = set([line for line in nonalpha_lines if re.match(mydigire, line)])
关于让匹配不区分大小写,你可以使用 I
或者 IGNORECASE
这些标志,来自 re
模块,比如在编写你的正则表达式时:
regex = re.compile("^[a-ząčęėįšųūž]+_\d+$", re.I)
至于去掉那些不符合这个正则表达式的行,你可以简单地构建一个新的字符串,只包含那些符合的行:
new_s = "\n".join(line for line in s.split("\n") if re.match(regex, line))