使用Python2.6解析Bash输出

时间:2012-04-11 03:00:07

标签: python bash parsing variables

我是一个蟒蛇新手,我在这里挣扎着一些概念 - 感谢任何帮助。

我有一个查询数据库的自定义系统工具,并返回几行作为要读取的结果 - 每行一个。以下python脚本从raw_input接受站点FQDN并在该fqdn上运行$ path。

#!/usr/bin/python

import subprocess
import getpass

#get the site name.
site = raw_input("What is the name of the site?: ").strip()

#run path.
cmd = 'path '+ site;
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE);
path_output = p.stdout.read().strip().split('\n')

print path_output

返回如下结果:

['    fqdn          = www.hcasc.info', '    account_id    = 525925', '    parent_id     = 525925', '    nfs           = /mnt/stor7-wc2-dfw1/525925/www.hcasc.info', '  server_type   = PHP5', '    ssl           = False', '    host_ip       = 98.129.229.186', '    cgi_hosting   = False', '    test_link_ip  = 98.129.229.186', '    ipv6_ip       = 2001:4800:7b02:100::1600:0']

如何从“nfs = etc”中获取额外的空格,或者只取第三列(又名awk'{print $ 3}')和/或将这些结果的每一部分从bash分配给单独的变量进一步操纵?

在安装此学习曲线时遇到一些麻烦,我们非常感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

第三栏是line.split()[2];如果你想丢掉前两个单词并接受其余的话,那就是line.split(None, 2)[-1]。 (split没有参数,或None作为第一个参数,在任何空格上分割。)

>>> '    fqdn          = www.hcasc.info'.split()
['fqdn', '=', 'www.hcasc.info']

>>> for var, equals, rest in (l.split(None, 2) for l in path_output):
    assert equals == '='
    print var, 'is', rest

fqdn is www.hcasc.info
account_id is 525925
parent_id is 525925
nfs is /mnt/stor7-wc2-dfw1/525925/www.hcasc.info
server_type is PHP5
ssl is False
host_ip is 98.129.229.186
cgi_hosting is False
test_link_ip is 98.129.229.186
ipv6_ip is 2001:4800:7b02:100::1600:0

说明: (l.split(None, 2) for l in path_output)是一个生成器表达式,它为l.split(None, 2)的每个值运行path_output(称之为l)。它就像一个列表理解,它是相同的,但它周围有[]而不是(),但只有当l.split循环遍历它时它才会运行for调用然后忘记以前的值,而列表推导将首先在每个步骤构造一个包含l.split的所有结果的大列表,然后通常循环遍历该列表。这种方式就像在做

for line in path_output:
    var, equals, rest = line.split(None, 2)
    ...
但是要短一点。 :)


如果您想将其放入字典中,如DSM suggests,则可以通过这种方式(仅针对上下文)执行此操作

d = dict((var, rest) for var, equals, rest in (l.split(None, 2) for l in path_output))

或者,在Python 2.7 / 3中,更好的

d = { var: rest for var, equals, rest in (l.split(None, 2) for l in path_output) }

当然,您可以在两行中使其更具可读性:

output_vals = (l.split(None, 2) for l in path_output)
d = dict((var, rest) for var, equals, rest in output_vals)

无论你想要一个字典还是一个循环,取决于你将要用它做什么处理,但字典对于大多数事情来说可能是一种更好的方法。

答案 1 :(得分:0)

第二个问题:您可以在列表中收集结果,但使用字典更方便。

第一个问题:由于您的结果都是key = value形式,因此您可以像这样提取它们:

results = dict()
for line in p.stdout:
    key, value = line.split('=')
    results[key.strip()] = value.strip()

当像这样调用p.stdout(或任何文本文件对象)时,它一次隐含地读取一行。下一个语句在等号上分割线,并将这些部分分配给两个变量。最后,我们在keyvalue周围删除空格并将它们存储在字典中。

PS。您还可以使用line.split()在空格上拆分该行;但如果密钥的值或(不太可能)包含嵌入空间,则会出现问题。