Açıkça hiçbir şey yapmaması şartıyla, kabuk komut dosyasında: komutunun faydası nedir?


27

Cevap olarak kabuk komut dosyası içinde yorumlarla ilgili bu soruya , belirtilmektedir :açıkça hiçbir şey yapmaz (ama yorumlar için kullanılacak değildir) boş komuttur.

Kesinlikle hiçbir şey yapmayan bir komutun faydası ne olurdu?



2
Ayrıca burada daha iyi bir cevaba sahip olan , yani yerleşik olması gereken , değişkenlerin kapsamını etkilemeyen, bu soruyu yanıtlayın:true
Old Pro

2
Açıkça incelikle hiçbir şey yapmaz .
mikeserv

Yanıtlar:


19

Genelde truedöngülerde kullanırım ; Bence daha açık:

while true; do
    ...
done

:Gerçekten kullanışlı bulduğum tek yer , bir şeyi eşleştirmeniz gerekiyorsa, ancak bir şey yapmak istemiyorsanız, durum ifadeleridir. Örneğin:

case $answer in
    ([Yy]*) : ok ;;
    (*)     echo "stop."; exit 1 ;;
esac

3
Katılıyorum. truebir durum :için, bir NOP için.
jw013

1
bash kabul eder case a in a ) ;; esac. Bunu kabul etmeyen kabukları var mı?
Kaz

@Kaz: göre POSIX kabuk dilbilgisi , case ${var} in value);; *) do_something;; esackabul edilebilir. :Komut boş durumlar için gerekli değildir.
Richard Hansen

12

Başlangıçta, C derlenmiş programın aksine bir Bourne kabuğu programı olduğunu belirlemek için kullanılmıştır. Bu, shebang ve çoklu betik dillerinden önceydi (csh, perl). Sadece ile başlayan bir betiği çalıştırabilirsiniz ::

$ echo : > /tmp/xyzzy
$ chmod +x /tmp/xyzzy
$ ./xyzzy

Genellikle betiği $SHELL(veya /bin/sh) 'ye karşı çalıştırır .

O zamandan beri, temel kullanım argümanları değerlendirmektir. Hala kullanıyorum:

: ${EDITOR:=vim}

bir komut dosyasında varsayılan bir değer belirlemek için.


11

: içinden sonlandırılması gereken döngüler yazmak için kullanışlıdır.

while :
do
    ...stuff...
done

Bu breakya exitda çağrılmadıkça sonsuza kadar çalışacak ya da kabuk bir sonlandırma sinyali alacaktır .


3
while true; do ...; doneNiyetleri okuyucuya daha iyi ilettiğini hissediyorumwhile :; do ...; done
Richard Hansen

9

Kabuk komut dosyasında "bir" ifadesi istediğinizde, ya bazı testler için sakıncalı görünebilecek bir "değil" koşulu kullanırsınız ya da yan tümcesinde gerçek kodda ':' kullanırsınız. fıkra.

if [ some-exotic-condition ]
then
    :
else
    # Real code here
fi

"Egzotik durum", olumsuzlamak istemediğiniz bir şey olabilir veya "negatif mantık" kullanmazsanız, bu çok daha net bir şekilde ortaya çıkabilir.


1
Ayrıca, boş dallar için autoconfbir varsayılan eklemek :durumun nasıl tersine çevrileceğini bulmaktan daha kolay olduğu için oluşturulan komut dosyalarında da gösterilir .
Dietrich Epp

2
!Önüne yapışmanın ne kadar saçma olduğunu göremiyorum [ some-exotic-condition ], ama : elseondan saçma değil sonra gereksiz .
Kaz

@Kaz'ın iyi bir noktası var. Egzotik koşullarla gelmenin en iyi ihtimalle zor olduğunu aklımızda tutalım. Hepsini yok etmek zorunda kalırsanız, bu bir şeydir, ancak durumu daha az belirgin hale getirebilir. '!' Yapar tüm durumu mu yoksa sadece ilk terimi mi olumsuzlarsınız? Bazen bir ':' gerçek cümlesine sahip olmak en iyisidir.
Bruce Ediger,

!Belirteci bütün bir komut boru elemanının ortadan kaldırır. while ! grep ... ; do ... done veya if ! [ ... ] ; then ... fi. Temel olarak test/[]sözdiziminde dışsaldır. Bkz .: pubs.opengroup.org/onlinepubs/9699919799/utilities/…
Kaz

5

Bunu sadece # karakterine ek olarak, bir satırın geçici olarak yorumlanması için # karakterine ek olarak kullandım; satırın yorumlanmasında, boş bir komut sırasına izin vermeme kabuğundaki bir hata nedeniyle satırın yorumlanmasında bir sözdizimi hatası oluştu. :

if condition ; then
    :# temporarily commented out command
fi

Bunlar olmadan: bir sözdizimi hatası olan eksik bir komut dizisine sahibiz.


4

:Yararlı bulduğum iki durum var :

Varsayılan değişken atamaları

#!/bin/sh

# set VAR to "default value" if not already set in the environment
: "${VAR=default value}"

# print the value of the VAR variable.  Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR}"

Bu, kabuk betiğinizin kullanıcılarının betiği düzenlemeden bir ayarı geçersiz kılmalarına izin vermenin uygun bir yoludur. (Bununla birlikte, komut satırı argümanları daha iyidir çünkü kullanıcı, dışa aktarılan ortamında kullandığınız değişkeni rastlantısal olarak kullanıyorsa, beklenmeyen davranış riskiyle karşılaşmazsınız.) Kullanıcı ayarı geçersiz kılar:

VAR="other value" ./script

${VAR=value}Sözdizimi setine diyor VARüzere valueeğer VARzaten ayarlı değil, daha sonra değişkenin değerine genişler. Henüz değişkenin değerini önemsemediğimiz için, no-op komutundan :kurtulmak için bir argüman olarak iletilir .

:İşlemsiz bir komut olsa da , :komut çalıştırılmadan önce kabuk tarafından genişleme gerçekleştirilir ( komut değil !), :Böylece değişken ataması hala gerçekleşir (eğer varsa).

Ayrıca truebunun yerine başka bir komutun kullanılması da kabul edilebilir :, ancak niyetin daha az açık olması nedeniyle kodun okunması zorlaşır.

Aşağıdaki komut dosyası da işe yarar:

#!/bin/sh

# print the value of the VAR variable.  Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR=default value}"

Ancak yukarıdakilerin korunması çok daha zordur. Bu satırın ${VAR}üstünde bir satır kullanılıyorsa , printfvarsayılan atama genişletmesinin taşınması gerekir. Geliştirici bu ödevi taşımayı unutursa, bir hata tanıtılır.

Boş bir koşullu bloğa koyacak bir şey

Boş koşullu bloklardan genellikle kaçınılmalıdır, ancak bazen yararlı olurlar:

if some_condition; then
    # todo:  implement this block of code; for now do nothing.
    # the colon below is a no-op to prevent syntax errors
    :
fi

Bazı insanlar boş bir gerçek ifbloğa sahip olmanın kodu okumayı testten daha kolay yapmaktan daha kolaylaştırabileceğini iddia eder . Örneğin:

if [ -f foo ] && bar || baz; then
    :
else
    do_something_here
fi

tartışmasız okumaktan daha kolaydır:

if ! [ -f foo ] || ! bar && ! baz; then
    do_something_here
fi

Bununla birlikte, boş bir gerçek bloktan daha iyi birkaç alternatif yaklaşım olduğuna inanıyorum:

  1. Durumu bir fonksiyona koyun:

    exotic_condition() { [ -f foo ] && bar || baz; }
    
    if ! exotic_condition; then
        do_something_here
    fi
  2. Koşulu küme parantezlerinin (veya parantezlerin içine koyun, ancak parantez alt alt işlem oluşturur) ve alt kabuk içindeki ortamda yapılan değişiklikler alt kabukların dışında görünmez):

    if ! { [ -f foo ] && bar || baz; } then
        do_something_here
    fi
  3. Yerine ||kullanın if:

    [ -f foo ] && bar || baz || {
        do_something_here
    }

    Tepkime şartlar gibi basit bir tek astar olduğunda bu yaklaşımı tercih ederim:

    log() { printf '%s\n' "$*"; }
    error() { log "ERROR: $*" >&2; }
    fatal() { error "$@"; exit 1; }
    
    [ -f foo ] && bar || baz || fatal "condition not met"

1

UNIX'in eski versiyonlarındaki eski burur öncesi kabuğunda, :komut başlangıçta etiketin belirlenmesi için tasarlanmıştı goto(girişi etiketin bulunduğu yere bağlayan ayrı bir komuttu, bu yüzden etiketler ayrı bir sözdizimi olamazdı). Kabuk if, ayrıca ayrı bir komut olduğunu da biliyor .) Yakında yorumlar için kullanıldı, daha önce bir yorum sözdizimi ( #geri alma için kullanılıyordu) ve bu günler her şey kadar uyumluluk için buralardaydı.


0

Hiçbir şey yapmayan bir ifade olarak kullanmaya ek olarak, tek ifadeleri yorumlamak için bunları argümanlara dönüştürerek kullanabilirsiniz:.


: echo write this line > myfileHala boş bir dosya oluşturacağından tam olarak yorumda bulunmayacak .
Arcege

5
Söz konusu linke açıklandığı gibi, :olduğu DEĞİL yeterli yorumlama mekanizması.
jw013
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.