Python - 用空格分割线?

时间:2015-07-02 15:29:06

标签: python split

我确定这是一个基本问题,但我已经花了大约一个小时就已经完成并且无法弄明白。我正在解析smartctl输出,这是我正在使用的数据样本:

smartctl 5.41 2011-06-09 r3365 [x86_64-linux-2.6.32-39-pve] (local build)
Copyright (C) 2002-11 by Bruce Allen, http://smartmontools.sourceforge.net

=== START OF INFORMATION SECTION ===
Device Model:     TOSHIBA MD04ACA500
Serial Number:    Y9MYK6M4BS9K
LU WWN Device Id: 5 000039 5ebe01bc8
Firmware Version: FP2A
User Capacity:    5,000,981,078,016 bytes [5.00 TB]
Sector Sizes:     512 bytes logical, 4096 bytes physical
Device is:        Not in smartctl database [for details use: -P showall]
ATA Version is:   8
ATA Standard is:  Exact ATA specification draft version not indicated
Local Time is:    Thu Jul  2 11:24:08 2015 EDT
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

我想要实现的是拔出设备模型(某些设备只是一个字符串,其他设备,例如这个,它是两个字),序列号,时间和其他几个字段。我假设在冒号后捕获所有数据是最容易的,但是如何消除可变数量的空格?

以下是我目前提出的相关代码:

deviceModel = ""
serialNumber = ""
lines = infoMessage.split("\n")
for line in lines:
    parts = line.split()
    if str(parts):
        if parts[0] == "Device Model:     ":
            deviceModel = parts[1]
        elif parts[0] == "Serial Number:    ":
            serialNumber = parts[1]
vprint(3, "Device model: %s" %deviceModel)
vprint(3, "Serial number: %s" %serialNumber)

我不断得到的错误是:

File "./tester.py", line 152, in parseOutput
if parts[0] == "Device Model:     ":
IndexError: list index out of range

我得到错误所说的(有点),但我不确定该范围可能是什么,或者我是否以正确的方式尝试这个。寻找指导让我朝着正确的方向前进。非常感谢任何帮助。

谢谢!

7 个答案:

答案 0 :(得分:2)

当split返回长度为1或0的列表并访问第二个元素时,会发生IndexError。当没有找到要分割的东西(空行)时会发生这种情况。

不需要正则表达式:

deviceModel = ""
serialNumber = ""
lines = infoMessage.split("\n")

for line in lines:
    if line.startswith("Device Model:"):
        deviceModel = line.split(":")[1].strip()
    elif line.startswith("Serial Number:"):
        serialNumber = line.split(":")[1].strip()

print("Device model: %s" %deviceModel)
print("Serial number: %s" %serialNumber)

答案 1 :(得分:0)

我猜你的问题是中间的空行。因为,

>>> '\n'.split()
[]

你可以做点什么,

>>> f = open('a.txt')
>>> lines = f.readlines()
>>> deviceModel = [line for line in lines if 'Device Model' in line][0].split(':')[1].strip()
# 'TOSHIBA MD04ACA500'
>>> serialNumber = [line for line in lines if 'Serial Number' in line][0].split(':')[1].strip()
# 'Y9MYK6M4BS9K'

答案 2 :(得分:0)

我调试它的方法是在每次迭代时打印出parts。尝试并向我们展示失败时列表的内容。

编辑:您的问题很可能是@jonrsharpe所说的。当parts到达空行时,str(parts)可能是一个空列表,而'[]'只返回True var friend_marker = new google.maps .Marker({ map: map, position: location, icon: { url: icon.png }, zIndex: 1, draggable: true }); 。试着测试一下。

答案 3 :(得分:0)

尝试使用正则表达式:

import re

r = re.compile("^[^:]*:\s+(.*)$")
m = r.match("Device Model:     TOSHIBA MD04ACA500")
print m.group(1)   # Prints "TOSHIBA MD04ACA500"

答案 4 :(得分:0)

不确定您正在运行哪个版本,但在2.7上,line.split()逐字拆分,所以

>>> parts = line.split()
parts = ['Device', 'Model:', 'TOSHIBA', 'MD04ACA500']

您还可以尝试line.startswith()找到您想要的行https://docs.python.org/2/library/stdtypes.html#str.startswith

答案 5 :(得分:0)

我认为在这里使用正则表达式要容易得多。

import re

for line in lines:
    # Splits the string into at most two parts
    # at the first colon which is followed by one or more spaces
    parts = re.split(':\s+', line, 1)
    if parts:
        if parts[0] == "Device Model":
            deviceModel = parts[1]
        elif parts[0] == "Serial Number":
            serialNumber = parts[1]

请注意,如果您只关心这两个字段,startswith可能会更好。

答案 6 :(得分:0)

分割空白行时,parts是一个空列表。 您尝试通过检查空列表来容纳它,但是您将空列表转换为一个字符串,使您的条件语句为True。

>>> s = []
>>> bool(s)
False
>>> str(s)
'[]'
>>> bool(str(s))
True
>>> 

if str(parts):更改为if parts:

很多人会说使用try / except块对于Python来说是惯用的

for line in lines:
    parts = line.split()
    try:
        if parts[0] == "Device Model:     ":
            deviceModel = parts[1]
        elif parts[0] == "Serial Number:    ":
            serialNumber = parts[1]
    except IndexError:
        pass