shlex —単純な字句解析
ソースコード: :source: `Lib / shlex.py`
shlex クラスを使用すると、Unixシェルに似た単純な構文の字句アナライザーを簡単に作成できます。 これは、ミニ言語の記述(Pythonアプリケーションの実行制御ファイルなど)や引用符で囲まれた文字列の解析に役立つことがよくあります。
shlex モジュールは、次の関数を定義します。
- shlex.split(s, comments=False, posix=True)
シェルのような構文を使用して、文字列 s を分割します。 comments が False (デフォルト)の場合、指定された文字列内のコメントの解析は無効になります( shlex [の commenters 属性を設定します)。 X174X]インスタンスを空の文字列に)。 この関数はデフォルトでPOSIXモードで動作しますが、 posix 引数がfalseの場合は非POSIXモードを使用します。
- shlex.join(split_command)
リスト split_command のトークンを連結し、文字列を返します。 この関数は、 split()の逆です。
>>> from shlex import join >>> print(join(['echo', '-n', 'Multiple words'])) echo -n 'Multiple words'
戻り値は、インジェクションの脆弱性から保護するためにシェルエスケープされます( quote()を参照)。
バージョン3.8の新機能。
- shlex.quote(s)
文字列 s のシェルエスケープバージョンを返します。 戻り値は、リストを使用できない場合に備えて、シェルコマンドラインで1つのトークンとして安全に使用できる文字列です。
このイディオムは安全ではありません。
>>> 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)
shlex インスタンスまたはサブクラスインスタンスは、字句解析オブジェクトです。 初期化引数が存在する場合は、どこから文字を読み取るかを指定します。 これは、 read()および readline()メソッドを持つファイル/ストリームのようなオブジェクト、または文字列である必要があります。 引数が指定されていない場合、入力は
sys.stdin
から取得されます。 2番目のオプションの引数は、 infile 属性の初期値を設定するファイル名文字列です。 instream 引数が省略されているかsys.stdin
と等しい場合、この2番目の引数はデフォルトで「stdin」になります。 posix 引数は、動作モードを定義します。 posix がtrueでない場合(デフォルト)、 shlex インスタンスは互換モードで動作します。 POSIXモードで動作している場合、 shlex はPOSIXシェル解析ルールに可能な限り近づけようとします。 punctuation_chars 引数は、実際のシェルの解析方法に動作をさらに近づける方法を提供します。 これにはいくつかの値をとることができます。デフォルト値のFalse
は、Python3.5以前で見られた動作を維持します。True
に設定すると、文字();<>|&
の解析が変更されます。これらの文字(句読点と見なされる文字)の実行はすべて、単一のトークンとして返されます。 空でない文字列に設定すると、それらの文字が句読文字として使用されます。 punctuation_chars に表示される wordchars 属性の文字は、 wordchars から削除されます。 詳細については、シェルとの互換性の向上を参照してください。 punctuation_chars は、 shlex インスタンスの作成時にのみ設定でき、後で変更することはできません。バージョン3.6で変更: punctuation_chars パラメーターが追加されました。
shlexオブジェクト
shlex インスタンスには次のメソッドがあります。
- shlex.get_token()
- トークンを返します。 push_token()を使用してトークンがスタックされている場合は、スタックからトークンをポップします。 それ以外の場合は、入力ストリームから1つを読み取ります。 読み取りでファイルの即時終了が発生した場合、 eof が返されます(非POSIXモードでは空の文字列(
)、POSIXモードでは
None
)。
- shlex.push_token(str)
- 引数をトークンスタックにプッシュします。
- shlex.read_token()
- 生のトークンを読み取ります。 プッシュバックスタックを無視し、ソースリクエストを解釈しません。 (これは通常、有用なエントリポイントではなく、完全を期すためにのみここに記載されています。)
- shlex.sourcehook(filename)
shlex がソースリクエストを検出すると(以下の source を参照)、このメソッドには引数として次のトークンが与えられ、ファイル名と開いているファイルのようなオブジェクトで構成されるタプルを返すことが期待されます。
通常、このメソッドは最初に引数から引用符を取り除きます。 結果が絶対パス名である場合、以前のソースリクエストが有効になっていない場合、または以前のソースがストリーム(
sys.stdin
など)であった場合、結果はそのままになります。 それ以外の場合、結果が相対パス名の場合、ソースインクルージョンスタック上のファイルの直前のファイル名のディレクトリ部分が先頭に追加されます(この動作は、Cプリプロセッサが#include "file.h"
を処理する方法と似ています)。操作の結果はファイル名として扱われ、タプルの最初のコンポーネントとして返され、 open()が呼び出されて2番目のコンポーネントが生成されます。 (注:これは、インスタンスの初期化における引数の順序の逆です!)
このフックは公開されているため、ディレクトリ検索パス、ファイル拡張子の追加、およびその他の名前空間ハックを実装するために使用できます。 対応する「close」フックはありませんが、shlexインスタンスは、EOFを返すときに、ソース入力ストリームの close()メソッドを呼び出します。
ソーススタッキングをより明示的に制御するには、 push_source()および pop_source()メソッドを使用します。
- shlex.push_source(newstream, newfile=None)
- 入力ソースストリームを入力スタックにプッシュします。 filename引数を指定すると、後でエラーメッセージで使用できるようになります。 これは、 sourcehook()メソッドによって内部的に使用されるのと同じメソッドです。
- shlex.pop_source()
- 最後にプッシュされた入力ソースを入力スタックからポップします。 これは、レクサーがスタックされた入力ストリームでEOFに到達したときに内部的に使用されるのと同じ方法です。
- shlex.error_leader(infile=None, lineno=None)
このメソッドは、UnixCコンパイラエラーラベルの形式でエラーメッセージリーダーを生成します。 形式は
'"%s", line %d: '
で、%s
は現在のソースファイルの名前に置き換えられ、%d
は現在の入力行番号に置き換えられます(オプションの引数を使用して、これらをオーバーライドします)。この便利さは、 shlex ユーザーが、Emacsや他のUnixツールで理解できる標準の解析可能な形式でエラーメッセージを生成するように促すために提供されています。
shlex サブクラスのインスタンスには、字句解析を制御するか、デバッグに使用できるパブリックインスタンス変数がいくつかあります。
- shlex.commenters
- コメント初心者として認識される文字列。 コメントの開始から行末までのすべての文字は無視されます。 デフォルトでは
'#'
のみが含まれます。
- shlex.wordchars
- 複数文字のトークンに蓄積される文字列。 デフォルトでは、すべてのASCII英数字とアンダースコアが含まれます。 POSIXモードでは、Latin-1セットのアクセント付き文字も含まれます。 punctuation_chars が空でない場合、ファイル名の指定とコマンドラインパラメーターに表示される文字
~-./*?=
もこの属性に含まれ、 [に表示される文字もすべて含まれます。 X223X]が存在する場合、wordchars
から削除されます。 whitespace_split がTrue
に設定されている場合、これは効果がありません。
- shlex.whitespace
- 空白と見なされてスキップされる文字。 空白はトークンを制限します。 デフォルトでは、スペース、タブ、改行、およびキャリッジリターンが含まれます。
- shlex.escape
- エスケープと見なされる文字。 これはPOSIXモードでのみ使用され、デフォルトでは
'\'
のみが含まれます。
- shlex.quotes
- 文字列引用符と見なされる文字。 トークンは、同じ引用符が再び検出されるまで蓄積されます(したがって、シェルの場合と同様に、異なる引用符タイプが相互に保護します)。デフォルトでは、ASCIIの一重引用符と二重引用符が含まれます。
- shlex.whitespace_split
True
の場合、トークンは空白でのみ分割されます。 これは、たとえば、 shlex を使用してコマンドラインを解析し、シェル引数と同様の方法でトークンを取得する場合に役立ちます。 punctuation_chars と組み合わせて使用すると、トークンはそれらの文字に加えて空白で分割されます。バージョン3.8で変更: punctuation_chars 属性が whitespace_split 属性と互換性を持つようになりました。
- shlex.infile
- クラスのインスタンス化時に最初に設定された、または後のソース要求によってスタックされた、現在の入力ファイルの名前。 エラーメッセージを作成するときに、これを調べると役立つ場合があります。
- shlex.instream
- この shlex インスタンスが文字を読み取る入力ストリーム。
- shlex.source
- この属性は、デフォルトでは
None
です。 文字列を割り当てると、その文字列は、さまざまなシェルのsource
キーワードと同様の字句レベルの包含要求として認識されます。 つまり、直後のトークンがファイル名として開かれ、EOFまでそのストリームから入力が取得されます。EOFの時点で、そのストリームの close()メソッドが呼び出され、入力ソースが再び呼び出されます。元の入力ストリームになります。 ソースリクエストは、任意の数のレベルの深さまでスタックできます。
- shlex.debug
- この属性が数値で
1
以上の場合、 shlex インスタンスはその動作に関する詳細な進行状況出力を出力します。 これを使用する必要がある場合は、モジュールのソースコードを読んで詳細を学ぶことができます。
- shlex.lineno
- ソース行番号(これまでに見られた改行の数に1を加えたもの)。
- shlex.token
- トークンバッファ。 例外をキャッチするときにこれを調べると役立つ場合があります。
- shlex.eof
- ファイルの終わりを決定するために使用されるトークン。 これは、非POSIXモードでは空の文字列(
)に設定され、POSIXモードでは
None
に設定されます。
- shlex.punctuation_chars
読み取り専用プロパティ。 句読点と見なされる文字。 句読文字の実行は、単一のトークンとして返されます。 ただし、セマンティック妥当性チェックは実行されないことに注意してください。たとえば、シェルによって認識されない場合でも、「>>>」がトークンとして返される可能性があります。
バージョン3.6の新機能。
ルールの解析
非POSIXモードで動作している場合、 shlex は次のルールに従おうとします。
- 引用符は単語内で認識されません(
Do"Not"Separate
は単一の単語Do"Not"Separate
として解析されます)。 - エスケープ文字は認識されません。
- 文字を引用符で囲むと、引用符内のすべての文字のリテラル値が保持されます。
- 閉じ引用符は別々の単語を引用します(
"Do"Separate
は"Do"
およびSeparate
として解析されます)。 - whitespace_split が
False
の場合、単語文字、空白、または引用符として宣言されていない文字は、1文字のトークンとして返されます。True
の場合、 shlex は空白の単語のみを分割します。 - EOFは、空の文字列(
)で通知されます。
- 引用符で囲まれていても、空の文字列を解析することはできません。
POSIXモードで動作している場合、 shlex は次の解析ルールに従おうとします。
- 引用符は削除され、単語は分離されません(
"Do"Not"Separate"
は単一の単語DoNotSeparate
として解析されます)。 - 引用符で囲まれていないエスケープ文字(例:
'\'
)次の文字のリテラル値を保持します。 - エスケープされた引用符の一部ではない引用符で文字を囲む(例:
"'"
)引用符内のすべての文字のリテラル値を保持します。 - エスケープされた引用符の一部である引用符で文字を囲む(例:
'"'
)は、 escape で言及されている文字を除いて、引用符内のすべての文字のリテラル値を保持します。 エスケープ文字は、使用中の引用符またはエスケープ文字自体が後に続く場合にのみ、その特別な意味を保持します。 それ以外の場合、エスケープ文字は通常の文字と見なされます。 - EOFは、 None 値で通知されます。
- 引用符で囲まれた空の文字列(
)は許可されます。
シェルとの互換性の向上
バージョン3.6の新機能。
shlex クラスは、bash
、dash
、sh
などの一般的なUnixシェルによって実行される解析との互換性を提供します。 この互換性を利用するには、コンストラクターでpunctuation_chars
引数を指定します。 これはデフォルトでFalse
に設定され、3.6より前の動作が保持されます。 ただし、True
に設定されている場合、文字();<>|&
の解析が変更されます。これらの文字の実行はすべて単一のトークンとして返されます。 これはシェルの完全なパーサーには達していませんが(シェルの多様性を考えると、標準ライブラリの範囲外になります)、コマンドラインの処理を他の方法よりも簡単に実行できます。 説明のために、次のスニペットで違いを確認できます。
>>> 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', ')']
もちろん、シェルには無効なトークンが返されます。返されたトークンに対して独自のエラーチェックを実装する必要があります。
True
をpunctuation_charsパラメーターの値として渡す代わりに、特定の文字を含む文字列を渡すことができます。これは、句読点を構成する文字を判別するために使用されます。 例えば:
>>> 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?']
ただし、シェルをできるだけ一致させるために、 punctuation_chars を使用する場合は、常にposix
と whitespace_split を使用することをお勧めします。これにより、 wordchars が無効になります。 ] 全体的に。
最高の効果を得るには、punctuation_chars
をposix=True
と組み合わせて設定する必要があります。 (posix=False
は shlex のデフォルトであることに注意してください。)