Yerel değişken ataması için tırnak gerekli mi?


35

Yerel bir ödevin sağındaki tırnakları güvenle atlayabilir miyim?

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

Ben esas olarak ilgileniyorum bash, fakat diğer mermilerdeki köşe davaları ile ilgili herhangi bir bilgi açığız.


Sanırım sizin fonksiyonunuzda olduğu gibi bir satırda olsaydı farketmez. Ödevlerin alıntı yapılması gerekmez. Bkz. Mpi-sb.mpg.de/departments/rg1/teaching/unixffb-ss98/…
jirib

Yanıtlar:


40

Tırnaklar ihtiyaç vardır export foo="$var"ya da local foo="$var"(ya da readonly, typeset, declareve diğer değişken ilan komutlar olarak):

  • dash
  • shNetBSD (ayrıca Almquist kabuk göre).
  • shFreeBSD 9.2 veya daha büyük (bkz 9.3 değişikliği )
  • yash
  • zsh5.1'den önceki sürümlerde kshveya shöykünme sırasında (veya başka export var="$(cmd)"yerde zshsözcük ayırmayı nerede gerçekleştireceği içindir (globbing değil)).

Aksi taktirde değişken genişlemesi, herhangi başka bir komutta olduğu gibi herhangi bir argümandaki gibi sözcük bölmeye ve / veya dosya ismi oluşturulmasına tabi olacaktır.

Ve gerekli değildir:

  • bash
  • ksh (tüm uygulamalar)
  • shFreeBSD 9.3 veya daha yeni
  • busybox 'kül bazlı sh(2005'ten beri)
  • zsh

İçinde zsh, split + glob, parametrenin genişlemesi üzerine, içinde shveya öykünmedikçe asla yapılmaz ksh, ancak split (glob değil) komut değiştirme üzerine yapılır. 5.1 sürümünden beri export/ localve diğer bildirim komutları, yukarıdaki diğer kabuklarda olduğu gibi çift anahtar kelime / yerleşik komutlar haline gelmiştir ; bu, alıntı sh/ kshemülasyonda ve hatta komut değiştirme için bile alıntı yapılması gerekmediği anlamına gelir .

Aşağıdaki gibi kabuklarda bile alıntı yapılması gereken özel durumlar vardır:

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

Ya da daha genel olarak, eğer =(dahil olanlar dahil =) kalanlar kote edilmişse ya da bir genişlemenin sonucu (mesela export 'foo'="$var", export foo\="$var"ya da export foo$((n+=1))="$var"( $((...))gerçekte kote edilmelidir) ...). Ya da başka bir deyişle, eğer argüman exportgeçerli bir değişken ataması olmazsa yazılmamış olsaydı export.

Eğer export/ localkomut adı kendisi alıntılanmıştır (hatta gibi kısmen "export" a="$b", 'ex'port a="$b", \export a="$b"hatta ""export a="$b"), etrafında tırnak $bAT & T dışındaki ihtiyaç vardır kshve mksh.

Eğer export/ localveya bir kısmı bir miktar genişlemenin (içinde cmd=export; "$cmd" a="$b"veya hatta export$(:) a="$b") veya benzeri şeylerin sonucu dryrun=; $dryrun export a="$b"ise, her kabukta tırnaklar gerekir.

Bu durumda > /dev/null export a="$b", tırnaklara pdkshve türevlerinden bazılarına ihtiyaç duyulur .

İçin command export a="$b", tırnak her kabuk ancak ihtiyaç vardır mkshve ksh93(yaklaşık aynı uyarılar ile commandve exportbazı genişleme sonucu olarak).

Yazıldığında hiçbir kabuğa ihtiyaç duymazlar:

foo=$var export foo

(bu sözdizimi Bourne kabuğuyla da uyumludur ancak son sürümlerinde zsh, yalnızca sh/ kshöykünme sırasında çalışır).

( var=value local vardavranış kabukları arasında değişir gibi kullanılmaması gerektiğini unutmayın ).

Ayrıca kullanarak unutmayın exportbir atama ile de araçlar çıkış durumu olduğu cmdiçinde export var="$(cmd)"kaybolur. Bunu yapmanın bu export var; var=$(cmd)sorunu yok.

Ayrıca bu özel olaya dikkat edin bash:

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

Tavsiyem her zaman alıntı yapmak olacaktır.


3
zshTırnak işaretleri için gerekli olduğunu unutmayın; local foo="$(cmd)"çünkü , tırnak işaretleri altında olmayan (ancak dosya adı oluşturmayan) , tırnak işaretleri altında olmayan komut değiştirme işlemleri için (ancak KSH_TYPESETtırnak işaretleri olmadan parametre genişletmeleri için) yapılmaz (bu durumda tırnak işaretleri gerekli değildir) . Mantıklı olmak? Yok hayır? Sonra ne yaptığınızı tam olarak bilmediğiniz sürece her zaman her şeyi isteyin.
Matt

2
@Matt, sonucunu seviyorum. : D O komik, ben kabuk scripting öğrendiklerinizi çoğu bu Stack Exchange geldi, bu yüzden fark etmedi her zaman değişkenleri alıntı olduğu değil senaryo yazarları arasında ortak bilgi. Ben insanlar tarafından yazılmış üretim komut mevcut yapmak düzeltmeye çok şey var buluyorum yoktu alıntı ve vermedi onlar .... yaptıklarını tam olarak bilmek
Joker

3

Genelde, beyaz boşluklar gibi karakterlerin olabileceği değişkenlerin kullanımını alıntılarım. Aksi takdirde, bu gibi sorunlarla karşılaşırsınız:

#!/bin/bash

bar="hi bye"

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

foo

Değişkenin bir ödevde kullanımı, alıntılara ihtiyaç duymuyor gibi görünmektedir, ancak kullanmaya başladığınızda olduğu gibi, printforada alıntı yapmanız gerekir.

  printf "%s\n" "$myvar"

NOT: Değişkenin $IFS, ayırıcı karakterlerin ne olduğunu yöneten şey olduğunu unutmayın .

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>''.

Örnek

Bash'de hata ayıklama etkinken, sahne arkasında neler olduğunu görebiliriz.

$ 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

Yukarıda, değişkenin $barpara cezasına çarptırıldığını görebiliyoruz, $myvarancak kullanmaya gittiğimizde, kullanmaya başladığımız $myvarzamanın içeriğinin bir parçası olmalıydık $myvar.


2
sözcük bölme tırnaksız değişkenlerle tek sorun değil, (ki (her ikisi de) değişken atamaları ve için geçerli değildir gerçi yanı dosya adı nesil (aka globbing) düşünmek zorundayız bashve kshde local/ typeset... özel yerleşikleri).
Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.