Neden bir || ile birden fazla komut kullanmıyorsunuz? veya && şartlı çalışma?


12

Bu bir kabuk (bash, tire) isteminde çalışır:

[ -z "" ] && echo A || echo B
A

Ancak, bir POSIX kabuk komut dosyası yazmaya çalışıyorum , şöyle başlar:

#!/bin/sh

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

readonly raw_input_string=${1}

[ -z "${raw_input_string}" ] && echo "The given argument is empty."; exit 1

Ve nedenini bilmiyorum, ama mesajı almıyorum :

Verilen argüman boş.

Eğer betiği böyle çağırırsam:

./test_empty_argument ""

Neden?


5
Bkz. Bir değişkenin boş mu yoksa yalnızca boşluk içerip içermediğini nasıl test edebilirim? bir değişkenin boş, ayarlanmamış veya yalnızca boşluk içerip içermediğini test etme yolları için. Bu sorudaki sorunun bununla hiçbir ilgisi yok.
ilkkachu

1
Sadece kullanınif [ X”” = X”$var” ] ; then echo isempty ; fi
user2497

3
@ user2497 Bunu son 20 yıl içinde piyasaya sürülen kabuklarda kullanmak için hiçbir neden yoktur. Bu eski, buggy mermileri için bir çözüm.
chepner

@chepner Peki geçerli bir çözüm değil mi? Başka bir şey kullanılmalı mı?
user2497

6
[ "" = "$var" ]iyi çalışır; alıntılanan boş bir dize, argüman listesinden kaldırılmaz [. Ama bu da gerekli değil, çünkü [ -z "$var" ] aynı zamanda iyi çalışıyor.
chepner

Yanıtlar:


37

Hattınızın

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

bu aynı

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1

(alıntı ;yapılmayan, çoğu durumda yerine yeni satır karakteri konabilir)

Bu, exit 1ifadenin betiğe kaç bağımsız değişken iletildiğine bakılmaksızın her zaman yürütüldüğü anlamına gelir . Bu da mesajın The given argument is empty.hiçbir zaman yazdırılma şansının olmayacağı anlamına gelir .

"Kısa devre sözdizimi" kullanarak bir testten sonra tek bir deyimden fazlasını yürütmek için, ifadeleri gruplayın { ...; }. Alternatif, uygun bir ififade kullanmaktır (IMHO, bir komut dosyasında daha temiz görünür):

if [ "$#" -ne 1 ]; then
    echo 'Invalid number of arguments, expected one.' >&2
    exit 1
fi

İkinci testinizde de aynı sorun var.


ilişkin

[ -z "" ] && echo A || echo B

Bu, verilen örnek için işe yarar, ancak genel

some-test && command1 || command2

olur değil aynı olacak

if some-test; then
    command1
else
    command2
fi

Bunun yerine, daha çok

if ! { some-test && command1; }; then
    command2
fi

veya

if some-test && command1; then
    :
else
    command2
fi

Yani, test veya ilk komut başarısız olursa, ikinci komut yürütülür, bu da ilgili üç ifadenin tümünü yürütme potansiyeline sahip olduğu anlamına gelir .


18

Bu:

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

değil:

[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }

Ancak bunun yerine:

{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; } 
exit 1

Komut dosyanız, kaç bağımsız değişkene geçtiğinizden bağımsız olarak çıkıyor.


8

Daha okunabilir hale getirmenin bir yolu, aşağıdaki gibi bir dieişlev (a la perl) tanımlamaktır :

die() {
  printf >&2 '%s\n' "$@"
  exit 1
}

# then:

[ "$#" -eq 1 ] || die "Expected one argument, got $#"

[ -n "$1" ] || die "Empty argument not supported"

Gerekirse renkler, önek, satır numarası gibi daha fazla çan ve ıslık ekleyebilirsiniz.


Pratikte, diefonksiyonunuzu hiç birden fazla argümanla çağırdınız mı? (Öyleyse, bir örnek verebilir misiniz?) Neredeyse özdeş bir dieişlev kullanıyorum, ancak "$*"bunun yerine, niyetiniz ne olabilir?
jrw32982 Monica

3
Değeri, "$@"gerçek satırlar eklemeye gerek olmadan çok satırlı iletilere izin vermesidir.
Charles Duffy

1
@ jrw32982, "$*"argümanları boşluklarla birleştirmek için kullanılması , değiştirilmiş $IFSolanlar da dahil olmak üzere tüm bağlamlarda çalışması için SPC'ye ayarlamanız gerektiği anlamına gelir $IFS. Alternatif olarak ksh/ ile veya içinde zshkullanabilirsiniz . print -r -- "$@"echo -E - "$@"zsh
Stéphane Chazelas

@CharlesDuffy Evet, ama bunu bir -tip işlevi bağlamında yapıldığını hiç görmedim die. Ne soruyorum: pratikte, hiç kimse die "unable to blah:" "some error"2 satırlı bir hata mesajı almak amacıyla yazdığını gördün mü?
jrw32982 Monica

@ StéphaneChazelas İyi bir nokta. Yani (formülasyonumda) öyle olmalı die() { IFS=" "; printf >&2 "%s\n" "$*"; exit 1; }. Hiç bu tür bir dieişlevi printfbirden fazla argüman ileterek çok satırlı bir hata mesajı oluşturmak için kullandınız mı? Yoksa dieçıkışına yalnızca tek bir satırsonu ekleyecek şekilde yalnızca tek bir argüman iletdiniz mi?
jrw32982 Monica

-1

Sık sık boş bir dize testi olarak gördüm:

if [ "x$foo" = "x" ]; then ...

"=" - düzeltilmiş olmalıdır.
wef

3
Bu uygulama tam anlamıyla 1970'lerden. Kullanılan ve şimdi-obsolescent işlevsellik gibi alıntı doğru sürece (1992 POSIX sh standardına uyumlu herhangi kabuk üzerinden kullanmaya hiçbir sebep yoktur -a, -o, (ve )olarak derectives anlatmak için testtek bir çağırma birden operasyonlarını birleştirmek bundan kaçınılmalıdır; pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html adresindeki OB belirteçlerine bakın ).
Charles Duffy

Orijinal 'sh' ile '90'lara gönderilen linux dışı birleşimler - belki de hala. O zamanki işimde, taşınabilir kurulum komut dosyaları yazmak zorunda kaldım ve bu yapıyı kullandım. NVidia'nın linux için gönderdiği kurulum komut dosyalarına baktım ve hala bu yapıyı kullanıyorlar.
wef

NVidia kullanabilir, ancak bunun için herhangi bir teknik gerekçeleri olduğu anlamına gelmez; ticari UNIX'te kargo kültünün gelişimi ne yazık ki yaygın. Hatta Heirloom Bourne bile söz konusu hataya sahip değil - bu yüzden SunOS kod tabanı (POSIX olmayan bir gemi gönderen son ticari UNIX /bin/shve Heirloom Bourne'un öncülü olan) da buna sahip değildi.
Charles Duffy

1
Şapka takmıyorum, bu yüzden 1990'dan sonra bu hata ile ticari bir UNIX'te yayınlanan bir kabuğu açması gerekiyorsa, bir YouTube videosu yemeye söz veremem ... ama yapsaydım cazip olurdu . :)
Charles Duffy
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.