<p>要解决你的问题,你需要一个<a href="https://en.wikipedia.org/wiki/Parsing#Parser" rel="nofollow">parser</a>。在Python中有各种各样的库可用于解析,请参见sobatchelder的<a href="http://nedbatchelder.com/text/python-parsers.html" rel="nofollow">Python parsing tools</a>,以获得可用的库的列表。你知道吗</p>
<p>但是,您的数据格式并不太复杂,因此编写一个不依赖任何第三方模块的简单解析器非常容易。要将数据分解为单独的标记(aka<a href="https://en.wikipedia.org/wiki/Lexical_analysis" rel="nofollow">lexical analysis</a>),我们可以使用标准的<a href="https://docs.python.org/3/library/shlex.html" rel="nofollow">shlex</a>模块。你知道吗</p>
<p>下面的代码实现了一个非常简单的递归解析器。它是在Python2.6.6上开发和测试的,但是它应该在Python3上正常工作。您可能希望通过将其放入类中来封装它。我想这可能不是真的必要,但我想这取决于你的实际用例。你知道吗</p>
<p>这段代码使用<code>json</code>模块打印已解析的字典;这不是严格必要的,但它确实可以很容易地打印嵌套的字典。你知道吗</p>
<p>代码包含了一些错误检查,但是很容易被愚弄到接受奇怪的数据,因此如果不能保证输入数据总是正确的,您可能希望增强错误检查。你知道吗</p>
<pre><code>#!/usr/bin/env python
''' Parse config file data; see below for example data format
See http://stackoverflow.com/q/34898816/4014959
Written by PM 2Ring 2016.01.21
'''
from __future__ import print_function
import shlex
import string
import json
data = '''
router1 = {
hostname: abcd
interfaces:{
interface: gigabit 0/1
valn: 100
name: vlan1
ip_address: 1.1.1.1
}
clear: clear config all
}
'''
#Set up a simple lexer. `data` must be a file-/stream-like object
# with read() and readline() methods, or a string
lex = shlex.shlex(data)
lex.wordchars = string.ascii_letters + string.digits + "./:_"
def t_is(ch):
''' verify that the next token is ch '''
token = next(lex)
if token != ch:
raise ValueError('Line %d: Expected %r got %r'
% (lex.lineno, ch, token))
def get_word():
''' get next token if it's a word.
Otherwise, push it back & return None
'''
token = next(lex)
if token not in '{}':
return token
lex.push_token(token)
def is_key(token):
return token[-1] == ':'
def get_value():
''' get value, which may be a list of words or a dict '''
token = next(lex)
if token == '{':
#Value is a dict
lex.push_token(token)
return get_dict()
#Value consists of one or more non-key words
value = [token]
while True:
token = get_word()
if token is None:
break
if is_key(token):
lex.push_token(token)
break
value.append(token)
return ' '.join(value)
def get_dict():
''' parse a dictionary '''
t_is('{')
d = {}
while True:
#get key, value pairs
key = get_word()
if key is None:
t_is('}')
return d
if not is_key(key):
raise ValueError('Line %d: Bad key %r'
% (lex.lineno, key))
d[key[:-1]] = get_value()
def get_cfg():
''' parse config data, returning the name and the dict '''
name = get_word()
if name is None:
raise ValueError('Line %d: Expected name, got %r'
% (lex.lineno, next(lex)))
t_is('=')
d = get_dict()
return name, d
#
print(data)
print(20 * '- ' + '\n')
#for token in lex: print(token)
name, cfg = get_cfg()
print(name)
print(json.dumps(cfg, indent=4, sort_keys=True))
</code></pre>
<p><strong>输出</strong></p>
<pre><code>router1 = {
hostname: abcd
interfaces:{
interface: gigabit 0/1
valn: 100
name: vlan1
ip_address: 1.1.1.1
}
clear: clear config all
}
- - - - - - - - - - - - - - - - - - - -
router1
{
"clear": "clear config all",
"hostname": "abcd",
"interfaces": {
"interface": "gigabit 0/1",
"ip_address": "1.1.1.1",
"name": "vlan1",
"valn": "100"
}
}
</code></pre>