shlex
——简单词汇分析¶
源代码: Lib/shlex.py
这个 shlex
类使为类似于UnixShell的简单语法编写词汇分析器变得容易。这对于编写小型语言(例如,在Python应用程序的运行控制文件中)或分析带引号的字符串通常很有用。
这个 shlex
模块定义以下功能:
- shlex.split(s, comments=False, posix=True)¶
拆分字符串 s 使用类似shell的语法。如果 评论 是
False
(默认),将禁用解析给定字符串中的注释(设置commenters
的属性shlex
空字符串的实例)。默认情况下,此函数在POSIX模式下运行,但如果 位置 参数为假。3.9 版后已移除: 经过
None
对于 s 将在将来的Python版本中引发异常。
- shlex.join(split_command)¶
连接列表中的标记 split_command 并返回一个字符串。这个函数与
split()
.>>> from shlex import join >>> print(join(['echo', '-n', 'Multiple words'])) echo -n 'Multiple words'
返回的值是shell转义的,以防止注入漏洞(请参见
quote()
)3.8 新版功能.
- shlex.quote(s)¶
返回字符串的shell转义版本 s . 返回的值是一个字符串,可以安全地用作shell命令行中的一个标记,用于不能使用列表的情况。
警告
这个
shlex
模块是 仅为Unix shell设计 。这个
quote()
函数在不符合POSIX的外壳或来自其他操作系统(如Windows)的外壳上不保证正确。在这类shell上执行此模块引用的命令可能会造成命令插入漏洞。考虑使用将命令参数与列表一起传递的函数,例如
subprocess.run()
使用shell=False
。这个成语不安全:
>>> filename = 'somefile; rm -rf ~' >>> command = 'ls -l {}'.format(filename) >>> print(command) # executed by a shell: boom! ls -l somefile; rm -rf ~
quote()
让您堵住安全孔:>>> from shlex import quote >>> command = 'ls -l {}'.format(quote(filename)) >>> print(command) ls -l 'somefile; rm -rf ~' >>> remote_command = 'ssh home {}'.format(quote(command)) >>> print(remote_command) ssh home 'ls -l '"'"'somefile; rm -rf ~'"'"''
报价与unix shell和
split()
:>>> from shlex import split >>> remote_command = split(remote_command) >>> remote_command ['ssh', 'home', "ls -l 'somefile; rm -rf ~'"] >>> command = split(remote_command[-1]) >>> command ['ls', '-l', 'somefile; rm -rf ~']
3.3 新版功能.
这个 shlex
模块定义以下类:
- class shlex.shlex(instream=None, infile=None, posix=False, punctuation_chars=False)¶
A
shlex
实例或子类实例是词汇分析器对象。初始化参数(如果存在)指定从何处读取字符。它必须是一个类似文件/流的对象,read()
和readline()
方法或字符串。如果没有给出参数,输入将从sys.stdin
. 第二个可选参数是文件名字符串,它设置infile
属性。如果 流内 参数被省略或等于sys.stdin
,第二个参数默认为“stdin”。这个 位置 参数定义操作模式:何时 位置 不是真的(默认值),则shlex
实例将以兼容模式运行。在POSIX模式下操作时,shlex
将尽可能接近POSIX外壳解析规则。这个 punctuation_chars 参数提供了一种使行为更接近真实外壳解析的方法。这可以采用多个值:默认值,False
保留在python 3.5和更早版本下看到的行为。如果设置为True
,然后分析字符();<>|&
更改:这些字符(视为标点符号字符)的任何运行都作为单个标记返回。如果设置为非空字符串,则这些字符将用作标点符号。中的任何字符wordchars
出现在 punctuation_chars 将从中删除wordchars
. 见 改进了与外壳的兼容性 更多信息。 punctuation_chars 只能设置在shlex
实例创建,以后无法修改。在 3.6 版更改: 这个 punctuation_chars 已添加参数。
参见
- 模块
configparser
与Windows类似的配置文件的分析器
.ini
文件夹。
SLEX对象¶
A shlex
实例具有以下方法:
- shlex.get_token()¶
返回令牌。如果已使用
push_token()
从堆栈中弹出一个标记。否则,从输入流中读取一个。如果读取遇到文件的直接结尾,eof
返回(空字符串 (''
)在非POSIX模式下,以及None
在POSIX模式下。
- shlex.push_token(str)¶
将参数推送到令牌堆栈上。
- shlex.read_token()¶
读取原始令牌。忽略回推堆栈,不解释源请求。(这通常不是一个有用的入口点,在这里记录只是为了完整性。)
- shlex.sourcehook(filename)¶
什么时候?
shlex
检测源请求(请参见source
下面)将此方法作为参数提供以下标记,并期望返回一个由文件名和一个打开的类似文件的对象组成的元组。通常,此方法首先从参数中去掉任何引号。如果结果是绝对路径名,或者没有生效的先前源请求,或者先前的源是流(例如
sys.stdin
,结果将单独显示。否则,如果结果是相对路径名,则源包含堆栈上文件名前面的目录部分将被预先处理(此行为类似于C预处理器处理的方式#include "file.h"
)操作的结果将被视为文件名,并作为元组的第一个组件返回,其中
open()
调用它以生成第二个组件。(注意:这与实例初始化中的参数顺序相反!)这个钩子是公开的,因此您可以使用它来实现目录搜索路径、添加文件扩展名和其他名称空间黑客。没有对应的“close”挂钩,但shlex实例将调用
close()
源输入流返回EOF时的方法。要更明确地控制源堆栈,请使用
push_source()
和pop_source()
方法。
- shlex.push_source(newstream, newfile=None)¶
将输入源流推送到输入堆栈上。如果指定了文件名参数,它将在以后的错误消息中可用。这与
sourcehook()
方法。
- shlex.pop_source()¶
从输入堆栈中弹出最后一个推送的输入源。这与lexer在堆栈输入流上达到eof时在内部使用的方法相同。
- shlex.error_leader(infile=None, lineno=None)¶
此方法以unix c编译器错误标签的格式生成错误消息前导;格式为
'"%s", line %d: '
那里%s
替换为当前源文件的名称和%d
使用当前输入行号(可选参数可用于重写这些参数)。提供这种便利是为了鼓励
shlex
用户以Emacs和其他Unix工具理解的标准、可解析格式生成错误消息。
实例 shlex
子类具有一些公共实例变量,这些变量可以控制词法分析,也可以用于调试:
- shlex.commenters¶
被认为是注释初学者的字符串。从评论初学者到行尾的所有字符都被忽略。包括公正
'#'
默认情况下。
- shlex.wordchars¶
将累积为多字符标记的字符串。默认情况下,包括所有ASCII字母数字和下划线。在POSIX模式中,还包括拉丁-1集中的重音字符。如果
punctuation_chars
不是空的,字符~-./*?=
它可以出现在文件名规范和命令行参数中,也将包含在该属性中,以及出现在punctuation_chars
将从中删除wordchars
如果他们在那里。如果whitespace_split
设置为True
,这将没有效果。
- shlex.whitespace¶
将被视为空白并跳过的字符。空白边界标记。默认情况下,包括空格、制表符、换行和回车。
- shlex.escape¶
将被视为转义的字符。这将仅在POSIX模式中使用,并且仅包括
'\'
默认情况下。
- shlex.quotes¶
将被视为字符串引号的字符。令牌会累积,直到再次遇到同一个引号(因此,不同的引号类型会像shell中那样相互保护。)默认情况下,包括ASCII单引号和双引号。
- shlex.whitespace_split¶
如果
True
,标记将只被拆分为空白。例如,对于使用shlex
,以类似于shell参数的方式获取标记。与一起使用时punctuation_chars
,除这些字符外,标记将在空白处拆分。在 3.8 版更改: 这个
punctuation_chars
属性与whitespace_split
属性。
- shlex.infile¶
当前输入文件的名称,如最初在类实例化时设置的,或由以后的源请求堆叠的。在构造错误消息时检查这一点可能很有用。
- shlex.source¶
这个属性是
None
默认情况下。如果为其分配一个字符串,则该字符串将被识别为类似于source
各种外壳中的关键字。也就是说,紧接着的令牌将作为文件名打开,输入将从该流中获取,直到EOF,此时close()
将调用该流的方法,输入源将再次成为原始输入流。源请求可以层叠任意深度。
- shlex.lineno¶
源行号(到目前为止看到的新行数加上一行)。
- shlex.token¶
令牌缓冲区。在捕获异常时检查这一点可能很有用。
- shlex.eof¶
用于确定文件结尾的标记。这将被设置为空字符串 (
''
,在非POSIX模式下,以及None
在POSIX模式下。
- shlex.punctuation_chars¶
只读属性。将被视为标点符号的字符。标点字符的运行将作为单个标记返回。但是,请注意,不会执行语义有效性检查:例如,“>>>”可以作为令牌返回,即使shell可能不会将其识别为令牌。
3.6 新版功能.
解析规则¶
在非POSIX模式下操作时, shlex
将努力遵守以下规则。
单词中不能识别引号字符 (
Do"Not"Separate
被解析为单个单词Do"Not"Separate
;无法识别转义字符;
引号中的封闭字符保留引号中所有字符的文字值;
右引号分隔词 (
"Do"Separate
被解析为"Do"
和Separate
;如果
whitespace_split
是False
,任何未声明为单词字符、空格或引号的字符都将作为单个字符标记返回。如果是True
,shlex
只在空白处拆分单词;用空字符串表示EOF (
''
;即使引用了,也不可能解析空字符串。
在POSIX模式下操作时, shlex
将尝试遵守以下解析规则。
引号被删去,不分开单词 (
"Do"Not"Separate"
被解析为单个单词DoNotSeparate
;不带引号的转义字符(例如
'\'
)保留后面的下一个字符的文字值;引号中不属于
escapedquotes
(例如)"'"
)保留引号内所有字符的文字值;引号中包含的字符是
escapedquotes
(例如)'"'
)保留引号中所有字符的文字值,但中提到的字符除外。escape
. 转义符只有在使用中的引号或转义符本身之后才保留其特殊含义。否则转义符将被视为普通字符。EOF用一个
None
价值;带引号的空字符串 (
''
)是允许的。
改进了与外壳的兼容性¶
3.6 新版功能.
这个 shlex
类提供与常见的unix shell执行的分析的兼容性,如 bash
, dash
和 sh
. 要利用此兼容性,请指定 punctuation_chars
构造函数中的参数。默认为 False
保持3.6之前的行为。但是,如果设置为 True
,然后分析字符 ();<>|&
更改:这些字符的任何运行都作为单个令牌返回。虽然它缺少一个完整的shell解析器(考虑到shell的多样性,这将超出标准库的范围),但它确实允许您比其他方法更容易地执行命令行的处理。为了说明这一点,您可以在以下代码段中看到不同之处:
>>> import shlex
>>> text = "a && b; c && d || e; f >'abc'; (def \"ghi\")"
>>> s = shlex.shlex(text, posix=True)
>>> s.whitespace_split = True
>>> list(s)
['a', '&&', 'b;', 'c', '&&', 'd', '||', 'e;', 'f', '>abc;', '(def', 'ghi)']
>>> s = shlex.shlex(text, posix=True, punctuation_chars=True)
>>> s.whitespace_split = True
>>> list(s)
['a', '&&', 'b', ';', 'c', '&&', 'd', '||', 'e', ';', 'f', '>', 'abc', ';',
'(', 'def', 'ghi', ')']
当然,将返回对shell无效的令牌,并且您需要对返回的令牌实现自己的错误检查。
而不是传球 True
作为标点符号参数的值,可以传递带有特定字符的字符串,该字符串将用于确定构成标点符号的字符。例如::
>>> import shlex
>>> s = shlex.shlex("a && b || c", punctuation_chars="|")
>>> list(s)
['a', '&', '&', 'b', '||', 'c']
注解
什么时候? punctuation_chars
是指定的, wordchars
用字符扩充属性 ~-./*?=
. 这是因为这些字符可以出现在文件名(包括通配符)和命令行参数(例如 --color=auto
)。因此:
>>> import shlex
>>> s = shlex.shlex('~/a && b-c --color=auto || d *.py?',
... punctuation_chars=True)
>>> list(s)
['~/a', '&&', 'b-c', '--color=auto', '||', 'd', '*.py?']
但是,为了尽可能接近外壳,建议始终使用 posix
和 whitespace_split
使用时 punctuation_chars
,这将否定 wordchars
完全。
为了达到最佳效果, punctuation_chars
应与 posix=True
. (注意 posix=False
是的默认值 shlex
)