Python - 用空格分隔行?
Python - line split with spaces?
我确定这是一个基本问题,但我已经花了大约一个小时来解决这个问题,但还是不太明白。我正在解析 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
我明白了错误的意思(有点),但我不确定范围可能是什么,或者我是否以正确的方式尝试了这个。寻找指导让我朝着正确的方向前进。非常感谢任何帮助。
谢谢!
我猜你的问题是中间的空行。因为,
>>> '\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'
我调试它的方法是在每次迭代时打印出 parts
。尝试一下,并向我们展示失败时的列表。
编辑:您的问题很可能是@jonrsharpe 所说的。 parts
到达空行时可能是一个空列表,而 str(parts)
将只是 return '[]'
即 True
。尝试测试一下。
尝试使用正则表达式:
import re
r = re.compile("^[^:]*:\s+(.*)$")
m = r.match("Device Model: TOSHIBA MD04ACA500")
print m.group(1) # Prints "TOSHIBA MD04ACA500"
不确定您使用的是哪个版本 运行,但是在 2.7 上,line.split()
正在逐字拆分行,因此
>>> parts = line.split()
parts = ['Device', 'Model:', 'TOSHIBA', 'MD04ACA500']
您也可以尝试line.startswith()
找到您想要的行https://docs.python.org/2/library/stdtypes.html#str.startswith
当拆分 returns 长度为一或零的列表并且您访问第二个元素时,会发生 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)
我认为在这里使用正则表达式会容易得多。
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
可能会更好。
拆分空行时,parts
为空列表。
您尝试通过检查一个空列表来适应它,但是您将空列表转换为一个字符串,这会导致您的条件语句为真。
>>> 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
我确定这是一个基本问题,但我已经花了大约一个小时来解决这个问题,但还是不太明白。我正在解析 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
我明白了错误的意思(有点),但我不确定范围可能是什么,或者我是否以正确的方式尝试了这个。寻找指导让我朝着正确的方向前进。非常感谢任何帮助。
谢谢!
我猜你的问题是中间的空行。因为,
>>> '\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'
我调试它的方法是在每次迭代时打印出 parts
。尝试一下,并向我们展示失败时的列表。
编辑:您的问题很可能是@jonrsharpe 所说的。 parts
到达空行时可能是一个空列表,而 str(parts)
将只是 return '[]'
即 True
。尝试测试一下。
尝试使用正则表达式:
import re
r = re.compile("^[^:]*:\s+(.*)$")
m = r.match("Device Model: TOSHIBA MD04ACA500")
print m.group(1) # Prints "TOSHIBA MD04ACA500"
不确定您使用的是哪个版本 运行,但是在 2.7 上,line.split()
正在逐字拆分行,因此
>>> parts = line.split()
parts = ['Device', 'Model:', 'TOSHIBA', 'MD04ACA500']
您也可以尝试line.startswith()
找到您想要的行https://docs.python.org/2/library/stdtypes.html#str.startswith
当拆分 returns 长度为一或零的列表并且您访问第二个元素时,会发生 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)
我认为在这里使用正则表达式会容易得多。
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
可能会更好。
拆分空行时,parts
为空列表。
您尝试通过检查一个空列表来适应它,但是您将空列表转换为一个字符串,这会导致您的条件语句为真。
>>> 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