ローカル変数の割り当てには引用符が必要ですか?


36

ローカル割り当ての右側の引用符を安全に省略できますか?

function foo {
    local myvar=${bar}
    stuff()
}

私は主に興味がbashありますが、他のシェルのコーナーケースに関する情報は大歓迎です。


あなたの関数にあるように、それが1行にある場合、それは何の違いもないと思います。割り当てには引用符は必要ありません。mpi-sb.mpg.de/departments/rg1/teaching/unixffb-ss98/…を
jirib

回答:


41

引用符はで必要とされるexport foo="$var"local foo="$var"(またはreadonlytypesetdeclareおよびその他の変数宣言コマンドで):

  • dash
  • shNetBSD(またAlmquistシェルに基づきます)。
  • shFreeBSDの9.2以前の(参照9.3の変化を
  • yash
  • zsh5.1 in kshまたはshエミュレーションより前のバージョン(またはそれ以外の場合(グロビングではなく)単語分割を実行するexport var="$(cmd)"場所zsh)。

それ以外の場合、変数の展開は、他のコマンドの引数のように、単語の分割やファイル名の生成の対象となります。

また、次のものには必要ありません。

  • bash
  • ksh (すべての実装)
  • shFreeBSDの9.3以降の
  • busybox '灰ベースsh(2005年以降)
  • zsh

ではzsh、in shまたはkshエミュレーションでない限り、split + globはパラメーター展開時に行われませんが、コマンド置換時にsplit(globではなく)が行われます。バージョン5.1以降、export/ localおよびその他の宣言コマンドは、上記の他のシェルのようにデュアルキーワード / 組み込みコマンドになっています。つまり、sh/ kshエミュレーションやコマンド置換でも引用符は不要です。

これらのシェルでもクォートが必要な特別な場合があります:

a="b=some value"
export "$a"

または、より一般的に、=(を含む=)の残りが引用されるか、何らかの拡張の結果(export 'foo'="$var"export foo\="$var"またはexport foo$((n+=1))="$var"$((...))実際に引用されるべきです)...)または、の引数exportexport

場合export/ localコマンド名自体が引用されている(でも同様の部分には"export" a="$b"'ex'port a="$b"\export a="$b"、またはさえ""export a="$b")、周りの引用符は$bAT&T以外で必要とされているkshmksh

場合はexport/ local(のようにいくつかの拡張の結果であるか、それの一部cmd=export; "$cmd" a="$b"あるいはexport$(:) a="$b"またはのようなもので)dryrun=; $dryrun export a="$b")、その後、引用符は、すべてのシェルで必要とされます。

の場合> /dev/null export a="$b"、引用符pdkshとその派生物の一部が必要です。

の場合command export a="$b"、引用符はすべてのシェルで必要ですがmkshksh93commandおよびexport拡張の結果についてではなく、同じ警告があります)。

記述されている場合、これらはシェルでは必要ありません。

foo=$var export foo

(その構文はBourneシェルとも互換性がありますが、の最新バージョンでzshsh/ kshエミュレーションでのみ機能します)。

var=value local var動作はシェルによって異なるため、使用しないでください)。

またexport、割り当てで使用すると、cmdin の終了ステータスexport var="$(cmd)"が失われることにもなります。export var; var=$(cmd)そんなことはありません。

また、次の特殊なケースにも注意してくださいbash

$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b

私のアドバイスは、常に引用することです。


3
そのノートzsh引用符されるために必要local foo="$(cmd)"wordsplitting(ただし、ファイル名の生成)があるためされ引用符で囲まれていないコマンド置換を行う(ただし、引用符で囲まれていないパラメータ展開のためには)、ない限りは、KSH_TYPESETケースの引用符をする、有効化されていない必要。理にかなっていますか?いや?次に、何をしているのか正確にわからない限り、常にすべてを引用します。
マット

2
@マット、あなたの結論が大好きです。:D面白いことです。シェルスクリプトについて学んだことのほとんどはこのスタック交換から得られたので、変数常に引用することはスクリプト作成者の間で一般的な知識ではないことに気づきませんでした。引用しておらず、彼らが何をしていたのか正確に知らなかった人々によって書かれた既存の本番スクリプトの修正がたくさんあることに
ワイルドカード

3

私は通常、空白などの文字が存在する可能性のある変数の使用法を引用しています。そうしないと、次のような問題が発生します。

#!/bin/bash

bar="hi bye"

function foo {
  local myvar=${bar}
  printf "%s\n" $myvar
  printf "%s\n" "$myvar"
}

foo

代入での変数の使用には引用符は必要ないようですが、変数を使用する場合は、引用符でprintf囲む必要があります。

  printf "%s\n" "$myvar"

注:変数$IFSは、区切り文字が何であるかを決定するものであることを忘れないでください。

IFS    The  Internal  Field  Separator that is used for word splitting after 
       expansion and to split lines into words with the read builtin command. 
       The default value is ``<space><tab><newline>''.

Bashでデバッグを有効にすると、舞台裏で何が起こっているかを確認できます。

$ bash -x cmd.bash 
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye

我々は変数が、ことがわかります上記で$barに罰金を渡された$myvar私たちが使用して行ったとき、次にけど$myvar、我々はの内容のcognoscenteしなければならなかった$myvar、我々はそれを使用するために行ったとき。


2
(つまり(両方)が変数割り当てにしては適用されませんが、単語の分割は、同様にあなたが(グロブ別名)ファイル名の生成を検討する必要があり、引用符で囲まれていない変数の唯一の問題ではないbashkshしてlocal/ typeset...特殊な組み込みコマンド)。
ステファンシャゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.