一般的なBashプログラミングエラー(終了)

Bash Pitfallsの翻訳の終わり。 前の部分はShellsブログ( パート1パート2 )と私のブログで利用可能です。



22.エコー「Hello World!」



問題は、Bashインタラクティブシェルでこのコマンドがエラーをスローすることです。

  bash :! ":イベントが見つかりません 


これは、デフォルト設定では、Bashが感嘆符を使用してcshスタイルのコマンド履歴展開を実行するためです。 スクリプトにはこのような問題はなく、対話型シェルでのみ問題があります。



ここでは明らかな解決策は機能しません。

  $ echo "こんにちは\!"
こんにちは\! 




この文字列を一重引用符で囲むことができます。

  echo 'Hello World!' 


ただし、ここで最も適切な解決策は、 histexpand



パラメーターを一時的にオフにすることです。 これは、 set +H



またはset +o histexpand



して実行できます。

 セット+ H
 echo "Hello World!" 


では、なぜ単一引用符を常に使用しないのですか? mp3ファイルに関する情報が必要だと想像してください。

  mp3info -t "表示させない" ...
 mp3info -t "Ah!Leah!"  ... 


単一引用符はここでは適切ではありません。なぜなら、曲名には名前にアポストロフィが含まれているためです。また、二重引用符を使用すると、コマンドの履歴の置換で問題が発生します(ファイル名に二重引用符も含まれている場合、それは一般に気の毒なことです)。 私は個人的に(テキストの作者であるGreg Wooledge)コマンド履歴置換を使用しないので、.bashrcにset +H



コマンドを追加するだけです。 しかし、これは習慣の問題であり、誰もが自分で決める。



23. $ *の引数



Bashには、Bourneシェルファミリの他のシェルと同様に、位置パラメータを順番に処理するための特別な構文がありますが、 $*



$@



必要なものではありません。パラメータ置換後、それらは単語のリストになり、パラメータのリストではなく、引数で渡されます。



正しい構文は次のとおりです。

  「$ @」の引数 


または単に:

  arg 


for arg in "$@"



for arg



一致for arg in "$@"



二重引用符で囲まれた変数"$@"



は、各コマンドライン引数を二重引用符で囲み、1つの単語のように見せるための特別なストリートマジックです。 つまり、 "$@"



リスト"$1" "$2" "$3"



などに変換されます。 このトリックはほとんどの場合に機能します。



例を考えてみましょう:

  #!/ bin / bash
 #間違っている
 xの$ *; する
 echo "パラメーター: '$ x'"
やった 


このコードは印刷されます:

  $ ./myscript 'arg 1' arg2 arg3
パラメーター: 'arg'
パラメーター: '1'
パラメーター: 'arg2'
パラメーター: 'arg3' 


外観は次のとおりです。

  #!/ bin / bash
 #正しい!
 「$ @」のx する
     echo "パラメーター: '$ x'"
やった 




  $ ./myscript 'arg 1' arg2 arg3
パラメーター: 'arg 1'
パラメーター: 'arg2'
パラメーター: 'arg3' 


24.関数foo()



一部のシェルではこれは機能しますが、すべてではありません。 function



定義するときに、 function



キーワードを角かっこ()と組み合わせないでください。



bashの一部のバージョンでは、 function



()



両方を同時に使用できますが、他のシェルでこれを行うことはできません。 ただし、一部のインタープリターはfunction foo



を受け入れfunction foo



が、最大限の互換性を確保するために以下を使用することをお勧めします。

  foo(){
  ...
 } 


25.エコー "〜"



チルダ展開は、〜文字が引用符で囲まれていない場合にのみ発生します。 この例では、 echo



はユーザーのホームディレクトリを一覧表示する代わりに、 ~



をstdoutに出力します。



~



代わりに$HOME



を使用して、ホームディレクトリに関連して表現されるパスで変数をエスケープする必要があります。

  "〜/ dir withスペ​​ース"# "〜/ dir withスペ​​ース"
 〜 "/ dir withスペ​​ース"# "〜/ dir withスペ​​ース"
 〜/ "スペースのあるディレクトリ"# "/ホーム/私の写真/スペースのあるディレクトリ"
 「$ホーム/スペースを含むディレクトリ」#「/ホーム/私の写真/スペースを含むディレクトリ」 


26. local varname = $(コマンド)



関数でローカル変数を定義することにより、 local



自体がコマンドとして機能します。 時には、これは文字列の残りの部分と不可解に相互作用する場合があります。 たとえば、次のコマンドで、置換されたコマンドの戻りコード($?)を受け取りたい場合、受け取ることはできません。ローカルコマンドの戻りコードがそれをオーバーライドします。



したがって、これらのコマンドは最適に分離されています。

 ローカル変数
 varname = $(コマンド)
 rc = $? 



All Articles