web-dev-qa-db-ja.com

コマンドライン引数でエスケープする必要がある文字は何ですか?

Bashでコマンドにコマンドライン引数を指定する場合、エスケープする必要がある文字は何ですか?

それらはBashのメタキャラクターに限定されていますか:スペース、タブ、|&;()<>

15
Tim

次の文字は、一部のコンテキストではシェル自体に特別な意味があり、引数でエスケープする必要がある場合があります。

それらのキャラクターのいくつかは、私がリンクしたものよりも多くのことで、より多くの場所で使用されています。


明示的にオプションであるいくつかのコーナーケースがあります。


改行のエスケープ 引用符が必要 —バックスラッシュは機能しません。 [〜#〜] ifs [〜#〜] にリストされているその他の文字も同様の処理が必要です。エスケープする必要はありません]または}、しかしあなたdoはエスケープする必要があります)演算子だからです。

これらのキャラクターの一部は、他のキャラクターよりも本当にエスケープする必要がある場合により厳しい制限があります。例えば、 a#bは問題ありませんが、a #bはコメントですが、>は両方のコンテキストでエスケープする必要があります。とにかく保守的にすべてをエスケープすることは害にならず、細かい違いを覚えるよりも簡単です。

コマンド名自体がシェルキーワード(iffordo)の場合は、エスケープまたは引用符で囲む必要があります。それらの中で唯一興味深いのはinです。これが常にキーワードであるかどうかは明らかではないためです。引数で使用するキーワードについてはしないでください。コマンドの名前を(ばかげて!)シェル演算子((&など)どこにいても常に引用する必要があります。


1Stéphaneは他の single-byteblank character from your locale もエスケープする必要があることに注意しています。最も一般的で実用的なロケールでは、少なくともCまたはUTF-8に基づくロケールでは、上記の空白文字のみです。一部のISO-8859-1ロケールでは、U + 00A0ノーブレークスペースは、Solaris、BSD、およびOS X(誤っていると思います)を含め、空白と見なされます。不明な任意のロケールを扱っている場合は、文字を含め、ほとんど何でも含めることができます。幸運を祈ります。

おそらく、空白と見なされる1バイトが内に空白ではないマルチバイト文字として表示される可能性があり、他の文字をエスケープする方法はありません。全体を引用符で囲むよりも。これは理論的な問題ではありません。上からのISO-8859-1ロケールでは、A0空白と見なされるバイトは、UTF-8エンコードされた「à」のようなマルチバイト文字に現れる可能性があります(C3 A0)。これらの文字を安全に処理するには、それらを引用符で囲む必要があります"à"。この動作は、スクリプトを作成した環境ではなく、スクリプトを実行している環境のロケール構成に依存します。

この振る舞いは複数の方法で壊れていると思いますが、私たちは対処されたハンドをプレイしなければなりません。非自己同期マルチバイト文字セットを使用している場合、最も安全な方法はすべてを引用することです。 UTF-8またはCを使用している場合は、安全です(現時点では)。

22
Michael Homer

GNU Parallelでは、これはテストされ、広範囲に使用されます:

$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
# quote newline as '\n'                                                                                                         
$a =~ s/[\n]/'\n'/go;

bashdashashkshzshfishでテストされています。一部の文字は一部の(バージョン)シェルで引用符を必要としませんが、上記はすべてのテスト済みシェルで機能します。

単に文字列を引用したい場合は、parallel --shellquoteにパイプできます。

printf "&*\t*!" | parallel --shellquote
3
Ole Tange

Perlの軽量エスケープソリューションでは、単一引用符の原則に従っています。単一引用符で囲まれたBash-stringには、単一引用符自体を除く任意の文字を含めることができます。

私のコード:

my $bash_reserved_characters_re = qr([ !"#$&'()*;<>?\[\\`{|~\t\n]);

while(<>) {
    if (/$bash_reserved_characters_re/) {
        my $quoted = s/'/'"'"'/gr;
        print "'$quoted'";
    } else {
        print $_;
    }
}

実行例1:

$ echo -n "abc" | Perl escape_bash_special_chars.pl
abc

実行例2:

echo "abc" | Perl escape_bash_special_chars.pl
'abc
'

実行例3:

echo -n 'ab^c' | Perl escape_bash_special_chars.pl
ab^c

実行例4:

echo -n 'ab~c' | Perl escape_bash_special_chars.pl
'ab~c'

実行例5:

echo -n "ab'c" | Perl escape_bash_special_chars.pl
'ab'"'"'c'

echo 'ab'"'"'c'
ab'c
1
Jari Turkia