shlex
--- 単純な字句解析¶
ソースコード: Lib/shlex.py
shlex
クラスは Unix シェルに似た、単純な構文に対する字句解析器を簡単に書けるようにします。このクラスはしばしば、 Python アプリケーションのための実行制御ファイルのような小規模言語を書く上で便利です。
shlex
モジュールは以下の関数を定義しています:
-
shlex.
split
(s, comments=False, posix=True)¶ シェルに似た文法を使って、文字列 s を分割します。 comments が
False
(デフォルト値) の場合、受理した文字列内のコメントを解析しません (shlex
インスタンスのcommenters
メンバの値を空文字列にします)。この関数はデフォルトでは POSIX モードで動作し、 posix 引数が偽の場合は非 POSIX モードで動作します。バージョン 3.9 で非推奨: Passing
None
for s will raise an exception in future Python versions.
-
shlex.
join
(split_command)¶ Concatenate the tokens of the list split_command and return a string. This function is the inverse of
split()
.>>> from shlex import join >>> print(join(['echo', '-n', 'Multiple words'])) echo -n 'Multiple words'
The returned value is shell-escaped to protect against injection vulnerabilities (see
quote()
).バージョン 3.8 で追加.
-
shlex.
quote
(s)¶ 文字列 s をシェルエスケープして返します。戻り値は、リストを使えないようなケースで、シェルコマンドライン内で一つのトークンとして安全に利用出来る文字列です。
警告
The
shlex
module is only designed for Unix shells.The
quote()
function is not guaranteed to be correct on non-POSIX compliant shells or shells from other operating systems such as Windows. Executing commands quoted by this module on such shells can open up the possibility of a command injection vulnerability.Consider using functions that pass command arguments with lists such as
subprocess.run()
withshell=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 シェルならびに
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
instance or subclass instance is a lexical analyzer object. The initialization argument, if present, specifies where to read characters from. It must be a file-/stream-like object withread()
andreadline()
methods, or a string. If no argument is given, input will be taken fromsys.stdin
. The second optional argument is a filename string, which sets the initial value of theinfile
attribute. If the instream argument is omitted or equal tosys.stdin
, this second argument defaults to "stdin". The posix argument defines the operational mode: when posix is not true (default), theshlex
instance will operate in compatibility mode. When operating in POSIX mode,shlex
will try to be as close as possible to the POSIX shell parsing rules. The punctuation_chars argument provides a way to make the behaviour even closer to how real shells parse. This can take a number of values: the default value,False
, preserves the behaviour seen under Python 3.5 and earlier. If set toTrue
, then parsing of the characters();<>|&
is changed: any run of these characters (considered punctuation characters) is returned as a single token. If set to a non-empty string of characters, those characters will be used as the punctuation characters. Any characters in thewordchars
attribute that appear in punctuation_chars will be removed fromwordchars
. See Improved Compatibility with Shells for more information. punctuation_chars can be set only uponshlex
instance creation and can't be modified later.バージョン 3.6 で変更: punctuation_chars 引数が追加されました。
参考
configparser
モジュールWindows
.ini
ファイルに似た設定ファイルのパーザ。
shlex オブジェクト¶
shlex
インスタンスは以下のメソッドを持っています:
-
shlex.
get_token
()¶ トークンを一つ返します。トークンが
push_token()
で使ってスタックに積まれていた場合、トークンをスタックからポップします。そうでない場合、トークンを一つ入力ストリームから読み出します。読み出し即時にファイル終了子に遭遇した場合、eof
(非 POSIX モードでは空文字列 (''
)、POSIX モードではNone
) が返されます。
-
shlex.
push_token
(str)¶ トークンスタックに引数文字列をスタックします。
-
shlex.
read_token
()¶ 生 (raw) のトークンを読み出します。プッシュバックスタックを無視し、かつソースリクエストを解釈しません (通常これは便利なエントリポイントではありません。完全性のためにここで記述されています)。
-
shlex.
sourcehook
(filename)¶ shlex
がソースリクエスト (下のsource
を参照してください) を検出した際、このメソッドはその後に続くトークンを引数として渡され、ファイル名と開かれたファイル類似オブジェクトからなるタプルを返すとされています。通常、このメソッドはまず引数から何らかのクオートを取り除きます。処理後の引数が絶対パス名であった場合か、以前に有効になったソースリクエストが存在しない場合か、以前のソースが (
sys.stdin
のような) ストリームであった場合、この結果はそのままにされます。そうでない場合で、処理後の引数が相対パス名の場合、ソースインクルードスタックにある直前のファイル名からディレクトリ部分が取り出され、相対パスの前の部分に追加されます (この動作は C 言語プリプロセッサにおける#include "file.h"
の扱いと同様です)。これらの操作の結果はファイル名として扱われ、タプルの最初の要素として返されます。同時にこのファイル名で
open()
を呼び出した結果が二つ目の要素になります (注意: インスタンス初期化のときとは引数の並びが逆になっています!)このフックはディレクトリサーチパスや、ファイル拡張子の追加、その他の名前空間に関するハックを実装できるようにするために公開されています。 'close' フックに対応するものはありませんが、shlex インスタンスはソースリクエストされている入力ストリームが EOF を返した時には
close()
を呼び出します。ソーススタックをより明示的に操作するには、
push_source()
およびpop_source()
メソッドを使ってください。
-
shlex.
push_source
(newstream, newfile=None)¶ 入力ソースストリームを入力スタックにプッシュします。ファイル名引数が指定された場合、以後のエラーメッセージ中で利用することができます。
sourcehook()
メソッドが内部で使用しているのと同じメソッドです。
-
shlex.
pop_source
()¶ 最後にプッシュされた入力ソースを入力スタックからポップします。字句解析器がスタック上の入力ストリームの EOF に到達した際に利用するメソッドと同じです。
-
shlex.
error_leader
(infile=None, lineno=None)¶ このメソッドはエラーメッセージの論述部分を Unix C コンパイラエラーラベルの形式で生成します; この書式は
'"%s", line %d: '
で、%s
は現在のソースファイル名で置き換えられ、%d
は現在の入力行番号で置き換えられます (オプションの引数を使ってこれらを上書きすることもできます)。このやり方は、
shlex
のユーザに対して、Emacs やその他の Unix ツール群が解釈できる一般的な書式でのメッセージを生成することを推奨するために提供されています。
shlex
サブクラスのインスタンスは、字句解析を制御したり、デバッグに使えるような public なインスタンス変数を持っています:
-
shlex.
commenters
¶ コメントの開始として認識される文字列です。コメントの開始から行末までのすべてのキャラクタ文字は無視されます。標準では単に
'#'
が入っています。
-
shlex.
wordchars
¶ The string of characters that will accumulate into multi-character tokens. By default, includes all ASCII alphanumerics and underscore. In POSIX mode, the accented characters in the Latin-1 set are also included. If
punctuation_chars
is not empty, the characters~-./*?=
, which can appear in filename specifications and command line parameters, will also be included in this attribute, and any characters which appear inpunctuation_chars
will be removed fromwordchars
if they are present there. Ifwhitespace_split
is set toTrue
, this will have no effect.
-
shlex.
whitespace
¶ 空白と見なされ、読み飛ばされる文字群です。空白はトークンの境界を作ります。標準では、スペース、タブ、改行 (linefeed) および復帰 (carriage-return) が入っています。
-
shlex.
escape
¶ エスケープ文字と見なされる文字群です。これは POSIX モードでのみ使われ、デフォルトでは
'\'
だけが入っています。
-
shlex.
quotes
¶ 文字列引用符と見なされる文字群です。トークンを構成する際、同じクオートが再び出現するまで文字をバッファに蓄積します (すなわち、異なるクオート形式はシェル中で互いに保護し合う関係にあります)。標準では、ASCII 単引用符および二重引用符が入っています。
-
shlex.
escapedquotes
¶ quotes
のうち、escape
で定義されたエスケープ文字を解釈する文字群です。これは POSIX モードでのみ使われ、デフォルトでは'"'
だけが入っています。
-
shlex.
whitespace_split
¶ If
True
, tokens will only be split in whitespaces. This is useful, for example, for parsing command lines withshlex
, getting tokens in a similar way to shell arguments. When used in combination withpunctuation_chars
, tokens will be split on whitespace in addition to those characters.バージョン 3.8 で変更: The
punctuation_chars
attribute was made compatible with thewhitespace_split
attribute.
-
shlex.
infile
¶ 現在の入力ファイル名です。クラスのインスタンス化時に初期設定されるか、その後のソースリクエストでスタックされます。エラーメッセージを構成する際にこの値を調べると便利なことがあります。
-
shlex.
source
¶ このメンバ変数は標準で
None
を取ります。この値に文字列を代入すると、その文字列は多くのシェルにおけるsource
キーワードに似た、字句解析レベルでのインクルード要求として認識されます。すなわち、その直後に現れるトークンをファイル名として新たなストリームを開き、そのストリームを入力として、EOF に到達するまで読み込まれます。新たなストリームの EOF に到達した時点でclose()
が呼び出され、入力は元の入力ストリームに戻されます。ソースリクエストは任意のレベルの深さまでスタックしてかまいません。
-
shlex.
debug
¶ このメンバ変数が数値で、かつ
1
またはそれ以上の値の場合、shlex
インスタンスは動作に関する冗長な進捗報告を出力します。この出力を使いたいなら、モジュールのソースコードを読めば詳細を学ぶことができます。
-
shlex.
lineno
¶ ソース行番号 (遭遇した改行の数に 1 を加えたもの) です。
-
shlex.
token
¶ トークンバッファです。例外を捕捉した際にこの値を調べると便利なことがあります。
-
shlex.
eof
¶ ファイルの終端を決定するのに使われるトークンです。非 POSIX モードでは空文字列 (
''
) 、POSIX モードではNone
が入ります。
-
shlex.
punctuation_chars
¶ A read-only property. Characters that will be considered punctuation. Runs of punctuation characters will be returned as a single token. However, note that no semantic validity checking will be performed: for example, '>>>' could be returned as a token, even though it may not be recognised as such by shells.
バージョン 3.6 で追加.
解析規則¶
非 POSIX モードで動作中の shlex
は以下の規則に従おうとします。
ワード内の引用符を認識しない (
Do"Not"Separate
は単一ワードDo"Not"Separate
として解析されます)エスケープ文字を認識しない
引用符で囲まれた文字列は、引用符内の全ての文字リテラルを保持する
閉じ引用符でワードを区切る (
"Do"Separate
は、"Do"
とSeparate
であると解析されます)whitespace_split
がFalse
の場合、wordchar、 whitespace または quote として宣言されていない全ての文字を、単一の文字トークンとして返す。True
の場合、shlex
は空白文字でのみ単語を区切る。空文字列 (
''
) で EOF を送出する引用符に囲んであっても、空文字列を解析しない
POSIX モードで動作中の shlex
は以下の解析規則に従おうとします。
引用符を取り除き、引用符で単語を分解しない (
"Do"Not"Separate"
は単一ワードDoNotSeparate
として解析されます)引用符で囲まれないエスケープ文字群 (
'\'
など) は直後に続く文字のリテラル値を保持するescapedquotes
でない引用符文字 ("'"
など) で囲まれている全ての文字のリテラル値を保持する引用符に囲まれた
escapedquotes
に含まれる文字 ('"'
など) は、escape
に含まれる文字を除き、全ての文字のリテラル値を保持する。エスケープ文字群は使用中の引用符、または、そのエスケープ文字自身が直後にある場合のみ、特殊な機能を保持する。他の場合にはエスケープ文字は普通の文字とみなされる。None
で EOF を送出する引用符に囲まれた空文字列 (
''
) を許す。
Improved Compatibility with Shells¶
バージョン 3.6 で追加.
The shlex
class provides compatibility with the parsing performed by
common Unix shells like bash
, dash
, and sh
. To take advantage of
this compatibility, specify the punctuation_chars
argument in the
constructor. This defaults to False
, which preserves pre-3.6 behaviour.
However, if it is set to True
, then parsing of the characters ();<>|&
is changed: any run of these characters is returned as a single token. While
this is short of a full parser for shells (which would be out of scope for the
standard library, given the multiplicity of shells out there), it does allow
you to perform processing of command lines more easily than you could
otherwise. To illustrate, you can see the difference in the following snippet:
>>> 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', ')']
Of course, tokens will be returned which are not valid for shells, and you'll need to implement your own error checks on the returned tokens.
Instead of passing True
as the value for the punctuation_chars parameter,
you can pass a string with specific characters, which will be used to determine
which characters constitute punctuation. For example:
>>> import shlex
>>> s = shlex.shlex("a && b || c", punctuation_chars="|")
>>> list(s)
['a', '&', '&', 'b', '||', 'c']
注釈
When punctuation_chars
is specified, the wordchars
attribute is augmented with the characters ~-./*?=
. That is because these
characters can appear in file names (including wildcards) and command-line
arguments (e.g. --color=auto
). Hence:
>>> import shlex
>>> s = shlex.shlex('~/a && b-c --color=auto || d *.py?',
... punctuation_chars=True)
>>> list(s)
['~/a', '&&', 'b-c', '--color=auto', '||', 'd', '*.py?']
However, to match the shell as closely as possible, it is recommended to
always use posix
and whitespace_split
when using
punctuation_chars
, which will negate
wordchars
entirely.
For best effect, punctuation_chars
should be set in conjunction with
posix=True
. (Note that posix=False
is the default for
shlex
.)