引用符なしでechoを実行するのは危険ですか?

引用符なしでechoを実行するのは危険ですか?

いくつかの同様のトピックを見たことがありますが、変数を引用しないという内容がありますが、これは望ましくない結果をもたらす可能性があることを知っています。

このコードを見て、次のコード行が実行されたときに実行するものを挿入できるかどうか疑問に思います。

echo run after_bundle

ベストアンサー1

上記のメモを追加してください。@Kusalanandaのすばらしい回答

echo run after_bundle

問題ありません。これは、3つのパラメータのどの文字もechoシェル固有の文字を含むように渡されないためです。

そして(ここでさらに言及したいことは)これらのバイトをシェル固有の文字に変換できるシステムロケールはありません。

これらの文字はすべて何ですか?POSIX呼び出しポータブル文字セット。これらの文字は、POSIXシステムのすべての文字セットに同じ方法で表示され、エンコードする必要があります。

したがって、コマンドラインはロケールに関係なく同じように解釈されます。

この移植可能な文字セットの外側の文字を使用し始めた場合は、その文字がシェルに特別でない場合でも、その文字を引用することをお勧めします。他のロケールでは、その文字を構成するバイトが別の文字として解釈される可能性があるためです。シェルスペシャルになります。コマンドを使用するかecho他のコマンドを使用するかは、echoシェルがコードを解析する方法ではありません。

たとえば、UTF-8では次のようになります。

echo voilà | iconv -f UTF-8 -t //TRANSLIT

エンコーディングはà0xc3 0xa0です。シェルスクリプトに対応するコード行があり、文字セットがUTF-8以外のロケールを使用しているユーザーがシェルスクリプトを呼び出す場合、これらの2バイトは非常に異なる文字を生成できるようになりました。

たとえば、fr_FR.ISO8859-15ロケールでは、一般的なフランス語ロケールは、フランス語を含む標準のシングルバイト文字セット(英語を含むほとんどの西ヨーロッパ言語と同じ)を使用し、0xc3バイトは文字として解釈され、Ã0xa0は文字として解釈されます。非文字セット。空白文字を破棄します。

NetBSD³などの一部のシステムでは、切り捨て防止スペースは次のように処理されます。スペース文字(isblank()trueを返し、一致)なので、[[:blank:]]シェルと同様にbash構文内のトークン区切り文字として扱われます。

echoこれは、as引数で実行するのではなく$'voil\xc3\xa0'as引数で実行しているため、正しく印刷されない$'voil\xc3'ことを意味しますvoilà

BIG5、BIG5-HKSCS、GB18030、GBKなどの中国語文字セットの場合、状況はさらに悪化します。この文字セットにはエンコーディングに、、|(最悪の例を挙げると)文字を含む文字が多くあります`。ではありませんが、0x5cでエンコードされているため、ほとんどのツールではまだ処理されています。\¥\\

たとえば、中国語のロケールを使用している場合は、zh_CN.gb18030次のスクリプトを作成できます。

echo 詜 reboot

スクリプトは、詜 rebootGB18030またはGBKを使用するロケール、唰 rebootBIG5またはBIG5-HKSCSを使用するロケール、ASCIIを使用するCロケール、またはISO8859-15またはUTF-8を使用するロケールとしてreboot出力されます。 GB18030 エンコーディングは0xd4 0x7c で、0x7c は ASCII エンコーディングなので、以下を|実行します。

 echo �| reboot

uname(しかし、�はロケールでレンダリングされた0xd4バイトを表します)reboot

$ echo $'echo \u8a5c uname' | iconv -t gb18030 > myscript
$ LC_ALL=zh_CN.gb18030 bash ./myscript | sed -n l
\324| uname$
$ LC_ALL=C bash ./myscript | sed -n l
Linux$

unameすでに実行中)。

したがって、私の提案は、移植可能な文字セットの外側の文字を含むすべての文字列を引用することです。

\ただし、andのエンコーディングはこれらの文字の一部のエンコーディングに見られるため、or(and / orはまだ特別です)を使用せずに移植可能な文字セットの外側の文字を参照することをお勧めし`ます。\"..."$'...'`\'...'

'私はロケールの文字セットにエンコーディングを含む文字(もちろんそれ自体を除く)があるシステムを知らないので、'これは'...'最も安全です。

一部のシェルは、$'\uXXXX'Unicodeコードポイントに基づく文字表現もサポートしています。zshWindowsやWindowsなどのシェルでは、bash文字はロケールの文字セットエンコーディングに挿入されます。ただし、文字セットにその文字がないと、予期しない動作が発生する可能性があります。これにより、シェルコードにASCII以外の文字を挿入することを防ぎます。

したがって、上記は次のようになります。

echo 'voilà' | iconv -f UTF-8 -t //TRANSLIT
echo '詜 reboot'

または:

echo $'voil\u00e0'
echo $'\u8a5c reboot'

(これらの文字を持たないロケールで実行すると、スクリプトがクラッシュする可能性があります。)

またはより良い理由は\echoまたは少なくとも一部 echo実装、少なくともUnix互換実装):

printf '%s\n' 'voilà' | iconv -f UTF-8 -t //TRANSLIT
printf '%s\n' '詜 reboot'

\最初の引数も特別なので、printfエンコードが含まれる場合はASCII以外の文字を避けるのが最善です\。)

次のタスクも実行できます。

'echo' 'voilà' | 'iconv' '-f' 'UTF-8' '-t' '//TRANSLIT'

(これは少し過剰ですが、ポータブル文字セットにどの文字があるのか​​わからない場合は、心を楽にすることができます)

また、古代`...`の形式のコマンド置換(他のレベルのバックスラッシュ処理を導入)を絶対に使用しない$(...)でください。


1は技術的にユーティリティechoに引数として渡され(呼び出し方法を知らせる)、3は今日のほとんどのシェルに組み込まれているので、3つの引数リストを持つファイルのエミュレーションはシェルで行われます。引数リストは、コマンドが主に機能する引数であるため、2番目の引数(to)で始まると考えるのが一般的です。echoargv[0]argcechoexec()/bin/echoargv[1]argv[argc - 1]

²注目すべき例外の1つは、文字セットにNor文字が含まれていja_JP.SJISないFreeBSDシステムのとんでもないロケールです。\~

³多くのシステム(FreeBSD、Solaris、GNUシステムを除く)はU + 00A0を[[:blank:]]UTF-8ロケールとして扱いますが、他のロケール(たとえばISO8859-15を使用するシステム)ではそうするシステムはほとんどありません。そのような問題。

おすすめ記事