Skip to content
Latchkey

shellのquotingとは何か?展開を制御する

shellのquotingは、テキストをリテラルとして扱うよう指示し、空白が引数を分割するか、変数やwildcardが展開されるかを制御します。

quotingはshellスクリプトの中で最もエラーが起きやすい部分の1つであり、最も重要な部分の1つでもあります。値をシングルクォート、ダブルクォート、あるいはクォートなしで囲むかによって、shellがそれを空白で分割するか、変数を展開するか、wildcardをglobするかが決まります。CIでの「pathに空白が入るまでは動く」というバグのほとんどは、クォート漏れに帰着します。

なぜquotingが存在するか

shellは通常、入力を空白で分割し、変数とwildcardを展開します。quotingはその一部またはすべてを一時停止し、空白や特殊文字を含め、テキストを書かれたとおりに渡せるようにします。

シングルクォートとダブルクォート

  • シングルクォートは完全にリテラルで、内部は何も展開されません。
  • ダブルクォートは変数とコマンドの置換を許しますが、word splittingとglobbingは防ぎます。
  • クォートなしは、完全な分割、展開、globbingを意味します。

典型的なバグ

クォートしないと、$FILEに空白が含まれる場合、shellがそれを2つの引数に分割するため、rm $FILEは壊れます。rm "$FILE"と書くとそれを1つに保ち、これが変数をほぼ常にダブルクォートで囲むべき理由です。

quotingと展開の組み合わせ

ダブルクォートはほとんどのスクリプトでちょうどよい選択です。$VARを介して変数の値を得られる一方、それらの値の中の空白はそのまま保たれ、wildcardが誤って展開されることもありません。

CIにおけるquoting

CIのpathや入力には、予期しなかった空白や特殊文字が含まれることがよくあります。"${INPUT}"のようにすべての変数展開をダブルクォートで囲むことは、pipelineでの謎めいたword splittingの失敗を避けるための最も効果的な習慣です。

マネージドrunnerでの堅牢なスクリプト

Latchkeyのrunnerでは、任意のLinux shellと同じquotingのルールが適用されます。set -uを一貫したダブルクォートと組み合わせると、未定義の変数と誤ってクォートされた変数の両方を、buildを壊す前に捉えられます。

重要なポイント

  • quotingはword splittingと、変数およびwildcardの展開を制御します。
  • シングルクォートはリテラルで、ダブルクォートは変数を展開しつつ空白をそのまま保ちます。
  • "$VAR"のようにすべての変数をダブルクォートで囲むと、CIスクリプトのバグのほとんどを防げます。

関連ガイド