在Python中解析用户输入
我正在尝试处理用户输入的内容,每个单词、名字或数字之间用空格分开(字符串用双引号包起来的除外),然后把这些内容放到一个列表里。这个列表会在处理的过程中打印出来。我之前写过这个代码的一个版本,但这次我想用“标记”(Tokens)来让代码看起来更整洁。下面是我目前写的代码,但它没有打印出任何东西。
#!/util/bin/python
import re
def main ():
for i in tokenizer('abcd xvc 23432 "exampe" 366'):
print (i);
tokens = (
('STRING', re.compile('"[^"]+"')), # longest match
('NAME', re.compile('[a-zA-Z_]+')),
('SPACE', re.compile('\s+')),
('NUMBER', re.compile('\d+')),
)
def tokenizer(s):
i = 0
lexeme = []
while i < len(s):
match = False
for token, regex in tokens:
result = regex.match(s, i)
if result:
lexeme.append((token, result.group(0)))
i = result.end()
match = True
break
if not match:
raise Exception('lexical error at {0}'.format(i))
return lexeme
main()
2 个回答
1
我觉得你的缩进有问题,像这样:
#!/util/bin/python
import re
tokens = (
('STRING', re.compile('"[^"]+"')), # longest match
('NAME', re.compile('[a-zA-Z_]+')),
('SPACE', re.compile('\s+')),
('NUMBER', re.compile('\d+')),
)
def main ():
for i in tokenizer('abcd xvc 23432 "exampe" 366'):
print (i);
def tokenizer(s):
i = 0
lexeme = []
while i < len(s):
match = False
for token, regex in tokens:
result = regex.match(s, i)
if result:
lexeme.append((token, result.group(0)))
i = result.end()
match = True
break
if not match:
raise Exception('lexical error at {0}'.format(i))
return lexeme
main()
会输出:
('NAME', 'abcd')
('SPACE', ' ')
('NAME', 'xvc')
('SPACE', ' ')
('NUMBER', '23432')
('SPACE', ' ')
('STRING', '"exampe"')
('SPACE', ' ')
('NUMBER', '366')
2
我建议使用 shlex
模块来分割带引号的字符串:
>>> import shlex
>>> s = 'hello "quoted string" 123 \'More quoted string\' end'
>>> s
'hello "quoted string" 123 \'More quoted string\' end'
>>> shlex.split(s)
['hello', 'quoted string', '123', 'More quoted string', 'end']
之后,你可以根据自己的需要对所有的标记(比如字符串、数字等)进行分类。唯一需要注意的是,shlex 不会处理空格。
这里有一个简单的示例:
import shlex
if __name__ == '__main__':
line = 'abcd xvc 23432 "exampe" 366'
tokens = shlex.split(line)
for token in tokens:
print '>{}<'.format(token)
输出结果:
>abcd<
>xvc<
>23432<
>exampe<
>366<
更新
如果你坚持不去掉引号,那么可以在调用 split() 时设置 posix=False
:
tokens = shlex.split(line, posix=False)
输出结果:
>abcd<
>xvc<
>23432<
>"exampe"<
>366<