Python正则表达式和选择列的建议
我想知道怎么用正则表达式,从一个文件中选择每行的前两列,这个文件有3列、4列或者更多列,列与列之间是用空格分开的(这些空格不是固定的,而是每行可能有多个空格)。
我的文件格式是:IP [空格] 子网掩码 [空格] 下一跳IP [换行]
所有行都是这个格式。我想提取出前两列(IP和子网掩码)。
这里有一个可以用来测试你正则表达式的例子:
10.97.96.0 10.97.97.128 47.73.1.0
47.73.4.128 47.73.7.6 47.73.8.0
47.73.15.0 47.73.40.0 47.73.41.0
85.205.9.164 85.205.14.44 172.17.103.0
172.17.103.8 172.17.103.48 172.17.103.56
172.17.103.96 172.17.103.100 172.17.103.136
172.17.103.140 172.17.104.44 172.17.105.28
172.17.105.32 172.17.105.220 172.17.105.224
别去关注具体的IP地址。我知道第二列并不是有效的地址掩码,这只是个例子。
我已经尝试过:
(?P<IP_ADD>\s*[1-9][0-9]{1,2}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})(?P<space>\s*)(?P<MASK>[1-9][0-9]{1,2}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(\s+|\D*))
但效果不是很好……
4 个回答
0
因为你需要“某种单行代码”,其实有很多方法可以做到,而不一定要用Python。比如:
| awk '{print $1,$2}'
你可以用任何能在标准输出(stdout)上输出你输入内容的东西。
0
编辑过的内容可以用来匹配任意数量的空格。
如果你知道要处理的内容是前两个用空格分开的值,可以使用Python的正则表达式来实现这个功能。
一个很不错的正则表达式速查表也能帮助你找到一些快捷的方法。像单词、空格和数字这样的特定符号类别都有一些小技巧。
import re
line = "10.97.96.0 10.97.97.128 47.73.1.0"
result = re.split("\s+", line)[0:2]
result
['10.97.96.0', '10.97.97.128']
1
这就是一个一行代码的写法:
[s.split()[:2] for s in string.split('\n')]
示例
string = """10.97.96.0 10.97.97.128 47.73.1.0
47.73.4.128 47.73.7.6 47.73.8.0
47.73.15.0 47.73.40.0 47.73.41.0
85.205.9.164 85.205.14.44 172.17.103.0
172.17.103.8 172.17.103.48 172.17.103.56
172.17.103.96 172.17.103.100 172.17.103.136
172.17.103.140 172.17.104.44 172.17.105.28
172.17.105.32 172.17.105.220 172.17.105.224"""
print [s.split()[:2] for s in string.split('\n')]
输出结果
[['10.97.96.0', '10.97.97.128']
['47.73.4.128', '47.73.7.6']
['47.73.15.0', '47.73.40.0']
['85.205.9.164', '85.205.14.44']
['172.17.103.8', '172.17.103.48']
['172.17.103.96', '172.17.103.100']
['172.17.103.140', '172.17.104.44']
['172.17.105.32', '172.17.105.220']]
1
使用正则表达式:
如果你想提取前两列,不管它们里面有什么内容,也不管它们之间有多少空格,你可以用 \S
(匹配任何非空格的字符)和 \s
(匹配空格)来做到这一点:
import re
lines = """
47.73.4.128 47.73.7.6 47.73.8.0
47.73.15.0 47.73.40.0 47.73.41.0
85.205.9.164 85.205.14.44 172.17.103.0
172.17.103.8 172.17.103.48 172.17.103.56
172.17.103.96 172.17.103.100 172.17.103.136
172.17.103.140 172.17.104.44 172.17.105.28
172.17.105.32 172.17.105.220 172.17.105.224
"""
regex = re.compile(r'(\S+)\s+(\S+)')
regex.findall(lines)
结果:
[('10.97.96.0', '10.97.97.128'),
('47.73.1.0', '47.73.4.128'),
('47.73.7.6', '47.73.8.0'),
('47.73.15.0', '47.73.40.0'),
('47.73.41.0', '85.205.9.164'),
('85.205.14.44', '172.17.103.0'),
('172.17.103.8', '172.17.103.48'),
('172.17.103.56', '172.17.103.96'),
('172.17.103.100', '172.17.103.136'),
('172.17.103.140', '172.17.104.44'),
('172.17.105.28', '172.17.105.32'),
('172.17.105.220', '172.17.105.224')]
不使用正则表达式
如果你不想用正则表达式,但仍然想处理多个空格,你也可以这样做:
while ' ' in lines: # notice the two-spaces-string
lines = lines.replace(' ', ' ')
columns = [line.split(' ')[:2] for line in lines.split('\n') if line]
优缺点:
使用正则表达式的好处是,如果分隔符中包含制表符,它也能正确解析数据,而第二种方法就做不到这一点。另一方面,正则表达式比简单的字符串分割需要更多的计算,这在处理非常大的数据集时可能会有影响。