模块来解析python中的简单语法
我的目标是在Linux下使用Python2.7.6阅读文件模块来解析python中的简单语法,python,dictionary,Python,Dictionary,我的目标是在Linux下使用Python2.7.6阅读文件/etc/os release,并获得一本字典。 该文件在Ubuntu中如下所示: NAME="Ubuntu" VERSION="14.04.2 LTS, Trusty Tahr" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 14.04.2 LTS" VERSION_ID="14.04" HOME_URL="http://www.ubuntu.com/" SUPPORT_URL="http:/
/etc/os release
,并获得一本字典。
该文件在Ubuntu中如下所示:
NAME="Ubuntu"
VERSION="14.04.2 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.2 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
我希望最终得到一个类似以下Python代码所创建的字典结果:
{
'NAME': 'Ubuntu',
'VERSION': '14.04.2 LTS, Trusty Tahr',
'ID': 'ubuntu',
'ID_LIKE': 'debian',
'PRETTY_NAME': 'Ubuntu 14.04.2 LTS',
'VERSION_ID': '14.04',
'HOME_URL': 'http://www.ubuntu.com/',
'SUPPORT_URL': 'http://help.ubuntu.com/',
'BUG_REPORT_URL': 'http://bugs.launchpad.net/ubuntu/',
}
我在Python库中找到了几个解析器,但每个解析器都解析了其他更复杂的语法。我在这里找到了一些例子,但都是关于更复杂的语法,并回答了如何编写解析器的问题。我只是在寻找一个已经存在的模块/函数。如果没有,那么,我将只编写自己的代码(因此我不寻找代码示例,除非这是我应该做的)。问题是,我甚至不知道这种语法的名称。虽然我目前的项目是将/etc/os release
作为一个字典,但我希望将来需要对类似语法的其他数据执行此操作,因此我的搜索重点是语法,而不是该文件
我认为这样简单的事情应该已经存在了
有趣的是,SO的代码示例显示突出显示了它,好像这里的web代码可以解析它,但这不是Python。只需通过拆分来创建自己的dict:
with open("/etc/os-release") as f:
d = {}
for line in f:
k,v = line.rstrip().split("=")
d[k] = v
print(d)
如果确实要删除引号,可以使用strip:
with open("/etc/os-release") as f:
d = {}
for line in f:
k,v = line.rstrip().split("=")
# .strip('"') will remove if there or else do nothing
d[k] = v.strip('"')
print(d)
{'VERSION': '14.04.2 LTS, Trusty Tahr', 'NAME': 'Ubuntu', 'HOME_URL': 'http://www.ubuntu.com/', 'ID': 'ubuntu', 'VERSION_ID': '14.04', 'SUPPORT_URL': 'http://help.ubuntu.com/', 'PRETTY_NAME': 'Ubuntu 14.04.2 LTS', 'BUG_REPORT_URL': 'http://bugs.launchpad.net/ubuntu/', 'ID_LIKE': 'debian'}
{'BUG_REPORT_URL': 'http://bugs.launchpad.net/ubuntu/',
'HOME_URL': 'http://www.ubuntu.com/',
'ID': 'ubuntu',
'ID_LIKE': 'debian',
'NAME': 'Ubuntu',
'PRETTY_NAME': 'Ubuntu 14.04.2 LTS',
'SUPPORT_URL': 'http://help.ubuntu.com/',
'VERSION': '14.04.2 LTS, Trusty Tahr',
'VERSION_ID': '14.04'}
Padraic Cunningham的答案是完美的,我只是继续回答第二部分(解析可以存在或不存在的引号):如果您想去掉所有引号,只需在Padraic的代码中添加两行即可
with open("/etc/os-release") as f:
d = {}
for line in f:
k,v = line.rstrip().split("=")
if v.startswith('"'):
v = v[1:-1]
d[k] = v
print(d)
这是因为我们可以假设,如果属性以双引号开始,它将以相同的方式结束。如果您希望单引号也具有相同的行为,只需在If中添加第二个条件 根据:
如果变量赋值值包含空格、分号或A-Z、A-Z、0-9之外的其他特殊字符,则必须用双引号或单引号括起来。Shell特殊字符(“$”、引号、反斜杠、反勾号)必须使用反斜杠转义,并遵循Shell样式。以“#”开头的行应作为注释忽略
在为文件编写解析器时,必须考虑上面引号中指定的每个规则。它很复杂,因为它被设计为作为shell脚本执行。实现这意味着实现shell的一部分
至于引号,它们除了包含复杂的字符串外没有其他意义,因此可以忽略。另一件事你必须考虑的是,由'= '分裂不是100%正确,因为在一行中可能有不止一个'= '。而是按第一个“=”的位置分开。它也可以用现代(3.5+)python实现为简单的dict理解: 这会生成一个这样的字典
{'name': 'Ubuntu',
'version': '18.04.2 LTS (Bionic Beaver)',
'id': 'ubuntu',
'id_like': 'debian',
'pretty_name': 'Ubuntu 18.04.2 LTS',
'version_id': '18.04',
'home_url': 'https://www.ubuntu.com/',
'support_url': 'https://help.ubuntu.com/',
'bug_report_url': 'https://bugs.launchpad.net/ubuntu/',
'privacy_policy_url': 'https://www.ubuntu.com/legal/terms-and-policies/privacy-policy',
'version_codename': 'bionic',
'ubuntu_codename': 'bionic'}
或者,我发现namedtuple非常有用:
from collections import namedtuple
with open('/etc/os-release') as f:
keys, values = zip(*[
(k.lower(), v.strip('\'"'))
for (k, v) in (
line.strip().split('=', 1) for line in f.read().strip().split('\n')
)]
)
r = namedtuple("OSRelease", keys)(*values)
这将生成一个namedtuple,其中所有变量都可以作为属性访问:
[ins] In [1]: from collections import namedtuple
...: with open('/etc/os-release') as f:
...: keys, values = zip(*[
...: (k.lower(), v.strip('\'"'))
...: for (k, v) in (
...: line.strip().split('=', 1) for line in f.read().strip().split('\n')
...: )]
...: )
...: r = namedtuple("OSRelease", keys)(*values)
[ins] In [2]: print(r)
OSRelease(name='Ubuntu', version='18.04.2 LTS (Bionic Beaver)', id='ubuntu', id_like='debian', pretty_name='Ubuntu 18.04.2 LTS', version_id='18.04', home_url='https://www.ubuntu.com/', support_url='https://help.ubuntu.com/', bug_report_url='https://bugs.launchpad.net/ubuntu/', privacy_policy_url='https://www.ubuntu.com/legal/terms-and-policies/privacy-policy', version_codename='bionic', ubuntu_codename='bionic')
[ins] In [3]: print(r.id)
ubuntu
[ins] In [4]: print(r.id_like)
debian
[ins] In [5]: print(r.version_id)
18.04
[ins] In [6]: print(r.ubuntu_codename)
bionic
但这不符合规程,规程是不需要的。。。目标是一个字典这将如何解析可能存在或可能不存在的引号?@Skaperen,你所说的解析可能存在或可能不存在的引号是什么意思?添加
maxslit=1
将防止字符串包含=
符号时出现问题。maxslit=1
应处理值中的=/code>。我不指望他们的名字。
[ins] In [1]: from collections import namedtuple
...: with open('/etc/os-release') as f:
...: keys, values = zip(*[
...: (k.lower(), v.strip('\'"'))
...: for (k, v) in (
...: line.strip().split('=', 1) for line in f.read().strip().split('\n')
...: )]
...: )
...: r = namedtuple("OSRelease", keys)(*values)
[ins] In [2]: print(r)
OSRelease(name='Ubuntu', version='18.04.2 LTS (Bionic Beaver)', id='ubuntu', id_like='debian', pretty_name='Ubuntu 18.04.2 LTS', version_id='18.04', home_url='https://www.ubuntu.com/', support_url='https://help.ubuntu.com/', bug_report_url='https://bugs.launchpad.net/ubuntu/', privacy_policy_url='https://www.ubuntu.com/legal/terms-and-policies/privacy-policy', version_codename='bionic', ubuntu_codename='bionic')
[ins] In [3]: print(r.id)
ubuntu
[ins] In [4]: print(r.id_like)
debian
[ins] In [5]: print(r.version_id)
18.04
[ins] In [6]: print(r.ubuntu_codename)
bionic