「ダッシュ」で実行するとprintfバイトフォーマットが失敗するのはなぜですか?

「ダッシュ」で実行するとprintfバイトフォーマットが失敗するのはなぜですか?

0のASCII 16進コードは0x30です。したがって、を実行してゼロを印刷でき、ゼロprintf '\x30'が印刷されます。

これを myScript.sh というシェルスクリプトに入れて実行すると、ゼロも./myScript.sh印刷されます。

sh -c printf '\x30'ただし、orを実行すると、sh myScript.sh単一バイトとして解釈されるのではなく、リテラル文字「\ x 30」が得られます。

なぜそんなことですか?

(この動作は複数のコンピュータで観察されており、すべてbashを実行していると思います。)

答え1

printf一部のシェルの実装(bash少なくともエミュレーションモードでもksh)はこれを16進数として理解します。しかし、これは本当ですzshsh\xHHHHprintf標準

POSIX規格には、1桁、2桁、または3桁の数字のprintfIDが必要です。\oooooo8進数型パラメータの数と型ディレクティブ\0oooで使用される%b引数の数(echo動作と一致させるため)。

/bin/shシステムに表示されるシェルは、一緒に使用すると8進数(すべての標準シェルと同様)を理解しますが、16進数は理解できませdashん。yashprintf

16進数30を8進数に変換すると60なので

$ sh -c 'printf "%b\n" "$1"' sh '\060'
0

または、8進数をパラメータとして渡したくないが、それを静的リテラルとして使用したい場合:

$ sh -c 'printf "\60\n"'
0

(あなたの質問のステートメントの違いに注意してくださいsh -c。ステートメント全体(引数を含む)は、ユーティリティオプションのオプションパラメータとして提供された文字列の一部です。printfあなたの質問の内容は単純な誤字であると仮定します。)sh-c

スクリプトが文字を正常に印刷する理由は、0スクリプトにシェル実行可能ファイルを指す#!-line があるか、bashいいえそのような行はまったくなく、代わりにスクリプトは対話型シェルで実行されますbashbash行なしでシェルスクリプトを実行する場合は、#!シェルを使用してbash実行します(参照:Shebangなしでスクリプトを実行するシェルインタプリタとは何ですか?これについての詳細は詳細)。

明示的なインタプリタ(図を参照)を使用してスクリプトを実行すると、この行sh myScript.sh#!存在する場合)は無視されます。

答え2

私が走るとき

$ sh -c printf '\x30'

わかりました。

printf: usage: printf [-v var] format [arguments]

すでに貴重なヒントを提供していますが、printf予想されるパラメータを取得できません。解決策は、コマンドパラメータを引用符で囲み、コマンドパラメータが複数のパラメータではなく単一の文字列であることを確認することです。もちろん、読みやすさを高めるために改行を追加することも悪くありません。

$ sh -c "printf '\x30\n'"
0

関連情報