使用Python的readline处理带引号的行

1 投票
3 回答
1298 浏览
提问于 2025-04-15 13:27

我写了一个简单的类似于命令行的程序,它使用了readline功能来智能补全输入的参数。我希望这个功能能够支持包含空格的参数,并且用引号括起来,这样它们就可以被当作一个参数来处理(就像在命令行中输入一样)。

我发现shlex.split()可以解析带引号的参数,但如果用户在输入过程中想要补全,就会出问题(比如:'complete "Hello ' 这种情况会导致shlex抛出异常,因为引号不匹配)。

有没有现成的代码可以做到这一点呢?

谢谢!

3 个回答

0

为了让@caxcaxcoatl的回答更通用一点,可以把代码中写死的版本替换成 readline.__file__,这样就能更灵活地使用了。

import ctypes
import readline

libreadline = ctypes.CDLL (readline.__file__)
rl_completer_quote_characters = ctypes.c_char_p.in_dll (
    libreadline, 
    "rl_completer_quote_characters"
)
rl_completer_quote_characters.value = '"'
1

GNU Readline 这个工具可以通过一个叫 rl_completer_quote_characters 的变量来实现某些功能。不过,遗憾的是,Python 的标准库中的 readline 模块并没有提供这个选项(即使在最新的 3.7.1 版本中也是如此)。

不过,我找到了一种使用 ctypes 来实现这个功能的方法:

import ctypes

libreadline = ctypes.CDLL ("libreadline.so.6")
rl_completer_quote_characters = ctypes.c_char_p.in_dll (
    libreadline, 
    "rl_completer_quote_characters"
)
rl_completer_quote_characters.value = '"'

需要注意的是,这个方法并不一定适用于所有环境(可能在不同的 Linux 版本之间也不行,因为 libreadline 的版本是硬编码的,而我电脑上没有普通的 libreadline.so),所以你可能需要根据自己的环境进行调整。

另外,在我的情况下,我只把双引号设置为补全功能的特殊字符,因为这是我需要的功能。

参考资料

2

我不知道有没有现成的代码可以用来完成这个任务,但如果是我来做的话,我会先捕捉到错误,然后试着在字符串的末尾加一个假的引号,看看shlex.split这个函数对修改后的字符串会有什么反应。

撰写回答