在调用lsof Im之后,寻找将每一行拆分成一个字符串的通用方法,从而在表的每个单元格中获得字符串,问题就出现了,因为每次调用命令时,每个列的大小都会发生变化。
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 8,1 4096 2 /
kthreadd 2 root txt unknown /proc/2/exe
kjournald 42 root txt unknown /proc/42/exe
udevd 77 root cwd DIR 8,1 4096 2 /
udevd 77 root txt REG 8,1 133176 139359 /sbin/udevd
flush-8:1 26221 root cwd DIR 8,1 4096 2 /
flush-8:1 26221 root rtd DIR 8,1 4096 2 /
flush-8:1 26221 root txt unknown /proc/26221/exe
sudo 26228 root 5u unix 0xfff999002579d3c0 0t0 515611 socket
python 30077 root 2u CHR 1,3 0t0 700 /dev/null发布于 2013-12-03 15:16:20
您知道,除了第一个和最后一个列标签外,列标签是对齐的。因此,您可以从列标签的结尾提取列边框(等效于:从相邻列标签之间的空白开始)。
import re
# assuming input_file to be a file-like object
header = input_file.next()
borders = [match.start() for match in re.finditer(r'\s+', header)]
second_to_third_border = borders[1]
borders = borders[1:-1] # delete the first and last because not right-aligned
for line in input_file:
first_to_second_border = line[:second_to_third_border].rfind(' ')
actual_borders = [0, first_to_second_border] + borders + [len(line)]
dset = []
for (s, e) in zip(actual_borders[:-1], actual_borders[1:]):
dset.append(line[s:e].strip())
print dset关于第一栏:
您可以搜索每行第一列和第二列之间的边框。从第二列和第三列之间的边框向后搜索空格。您应该向后执行,因为正如上面的注释中提到的那样,命令可能包含空格-- PID当然不是。
关于最后一栏:
列从第二、最后和最后的边框延伸到给定行的末尾。
示例:
from StringIO import StringIO
input_file = StringIO('''\
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 8,1 4096 2 /
kthreadd 2 root txt unknown /proc/2/exe
kjournald 42 root txt unknown /proc/42/exe
''')打印
['init', '1', 'root', 'cwd', 'DIR', '8,1', '4096', '2', '/']
['kthreadd', '2', 'root', 'txt', 'unknown', '', '', '', '/proc/2/exe']
['kjournald', '42', 'root', 'txt', 'unknown', '', '', '', '/proc/42/exe']发布于 2013-12-03 11:44:47
而不是解析lsof命令输出,而是安装psutil模块-它还具有跨平台的优点。
import psutil
def get_all_files():
files = set()
for proc in psutil.process_iter():
try:
files.update(proc.get_open_files())
except Exception: # probably don't have permission to get the files
pass
return files
print get_all_files()
# set([openfile(path='/opt/google/chrome/locales/en-GB.pak', fd=28), openfile(path='/home/jon/.config/google-chrome/Default/Session Storage/000789.log', fd=95), openfile(path='/proc/2414/mounts', fd=8) ... ]然后,您可以将其调整为包含父进程和其他信息,例如:
进口psutil
for proc in psutil.process_iter():
try:
fids = proc.get_open_files()
except Exception:
continue
for fid in fids:
#print dir(proc)
print proc.name, proc.pid, proc.username, fid.path
#gnome-settings-daemon 2147 jon /proc/2147/mounts
#pulseaudio 2155 jon /home/jon/.config/pulse/2f6a9045c2bc8db6bf32b2d7517969bf-device-volumes.tdb
#pulseaudio 2155 jon /home/jon/.config/pulse/2f6a9045c2bc8db6bf32b2d7517969bf-stream-volumes.tdb发布于 2013-12-03 11:33:26
那这个呢?
import fileinput
for line in fileinput.input():
print(line.split())你可以这样做:
lsof | python your_script.py解决“ NAME 问题”
为了解决注释中提到的名称栏中可能出现的空格问题,我可以提出以下解决方案。这是基于我保持简单的愿望,以及只有最后一列才能有空格的事实。
算法很简单: 1.找到最后一列开始的位置--我使用标题名开始位置2。在position>之后剪切行,您刚才所剪的是名称列的值。split()是行的其余部分。
以下是代码:
import fileinput
header_limits = dict()
records = list()
input = fileinput.input()
header_line = None
for line in input:
if not header_line:
header_line = line
col_names = header_line.split()
for col_name in col_names:
header_limits[col_name] = header_line.find(col_name)
continue
else:
record = dict()
record['NAME'] = line[header_limits['NAME']:].strip()
line = line[:header_limits['NAME'] - 1]
record.update(zip(col_names, line.split()))
records.append(record)
for record in records:
print "%s\n" % repr(record)结果是一个字典列表。每本字典都对应于输出的一行。
这是一个有趣的任务,展示了python对于日常任务的强大功能。
无论如何,如果可能的话,我更愿意使用一些python库作为建议的psutils
https://stackoverflow.com/questions/20349916
复制相似问题