「printf--」を使用することが推奨される理由「代わりに」エコ? 「[コピー]

「printf--」を使用することが推奨される理由「代わりに」エコ? 「[コピー]

内部にヘビーヒートトラップ「Greg's Wiki」で次の引用を見つけました。

実際、echoここでこのコマンドを使用することは絶対に安全ではありません。-nたとえば、変数に含まれる場合、echo印刷するデータではなくオプションと見なされます。変数値を印刷する絶対に信頼できる唯一の方法は、次の方法を使用することですprintf

printf "%s\n" "$foo"

しかし、私が入力したとき:

var="-n Hello"
echo "$var"

うまく機能し、オプションとして説明されていませんが、私が引用したソースから絶対に安全にするには、-nこの機能を使用する必要があると言う理由を理解できません。printf

答え1

あなたの例では、「偶然に」うまく動作します。その理由はこれだ

  • パラメータを1つだけ提供しましたecho
  • 提案されているように変数を参照しました。

つまり、「単語」の間のスペースを含む文字列だけがechoコマンドライン引数と見なされます。-n Helloecho(まあ、いくつかのs)はオプションを認識しますが、文字列は認識しないようにechoプログラムされているので、オプションであると仮定します。-n-n<space>Helloオペランド- つまり、「現状のまま」印刷したい文字列です(おそらく\シーケンスが拡張された状態で)。

使用したことがある場合

echo $var

引用符がなく、デフォルト値がある場合は$IFS空白$varに分割され、次のようechoに表示されます。二つ議論: -n-オプションとして解釈されます- そしてHello

これは意味するこの場合、シェル変数を正しく引用することは、echoオペランドがオプションとして解釈される状況が不注意に発生するのを防ぐ解決策です。

しかし:

  1. リンクされたソースの例は、「グローバル拡張」()を介してファイルのリストを印刷することです*.zip。ここで変数は〜しなければならない引用符なしで使用されるため、この保護は常に使用できるわけではありません。

  2. 参照変数は、次の状況でのみ有用です。噴射echoオプションパラメータが表示されます。。印刷したいパラメータが-n最初から単一のパラメータである場合、引用は役に立ちません。

    たとえば、printの文字列配列を収集し、文字列のecho1つが次のオプション引数でもある状況を考えてみますecho

    arguments=( "-n" "Hello" )
    

    その後、変数を正しく参照しても

    echo "${arguments[@]}"
    

    最初のトークンはechoまだ-nオペランドではないオプションと見なされます。複数の変数を引数としてecho渡し、最初の変数がorの場合も同様です-n。ここでも変数を引用することは役に立ちません。

  3. 一般に、プログラムが次の形式のパラメータを受け入れる場合は、引用さえ役に立ちません。-oValue

    仮想的な状況では、my_formula_renderer数学式をフォーマットし、オプションの引数を受け入れるプログラムを使用してください。次に、次の式を組版するとします。-sfontsize-sqrt(a^2 + b^2)

    ./my_formula_renderer "-sqrt(a^2+b^2)"
    

    プログラムに終了オプションの解析指定子がない場合は、上記の式のデフォルトのフォントサイズを使用するのではなく、フォントサイズの組版「--なし」を使用したいとします。qrt(a^2+b^2)

    ;-sなどの他の数式要素の間に明示的な空白がある場合でも役に立ちません。先行スペースがある「フォントサイズ」"-s +2t +u^2"と誤って解釈された可能性があります(参照+2t +u^2たとえば、この質問これが問題になります。)

  4. プログラムが単一文字オプションの「クラスタリング」を許可する場合も同様です。

    たとえば、@Stéphane Chazelasが指摘したように、echo文字列はoptionsとの接続として解釈される可能性があるため、その文字列を-neEenennne印刷しようとすると予期しない方法で失敗したり動作したりする可能性があります。-n-e-Eecho

  5. オプション処理に加えて、echo(一部のバージョンではデフォルトでオプションが有効になっている場合をecho含む一部)などが改行、バックスラッシュ、バックスペース文字に拡張されます。bashxpg_echo\n\\\bバックスラッシュを含めることができる蓄積文字列を出力するために使用することはできません。

TL/DR

核心は、あなたが引用したソースに「絶対」という言葉があり、echoそれが具体的に指す事実である。ほとんどの場合はecho大丈夫でしょう。しかし、盲目的に依存し始めると(近いうちに)何かが起こるechoか、実際にはもっと重要な別のプログラムになります。「オペランド」パラメータとして意図したものを誤って「オプション」パラメータとして誤って解釈する、通常はシェル変数として渡すとき。

関連情報