Kabuk betiğinde bir boole değerini temsil etmenin en iyi yolu nedir?


15

Biliyorum, içinde boolean değerler var bash, ama bunların hiçbir yerde kullanıldığını görmüyorum.

Makinemde sık sık aranan bazı bilgiler için bir sarıcı yazmak istiyorum, örneğin, bu özel USB sürücü takılı / takılı.

Bunu başarmak için en iyi uygulama hangisidir?

  • Dizi?

    drive_xyz_available=true
  • Bir sayı (true için 0, false için ≠ 0)?

    drive_xyz_available=0    # evaluates to true
  • Bir işlev?

    drive_xyz_available() { 
        if available_magic; then 
                return 0 
        else 
                return 1 
        fi
    }

Çoğunlukla, ambalajı kullanmak isteyen diğer insanlar tarafından ne beklendiğini merak ediyorum. Boolean bir değer, değişken gibi bir komut veya çağrılacak bir işlev bekliyorlar mı?

Güvenlik açısından, ikinci seçeneğin en güvenli olduğunu düşünürdüm, ancak deneyimlerinizi duymak isterim.


3
help true ; help false ; help exit
Costas

3
@Costas Ayrıntılı olarak düşünür müsünüz?
Minix

Yanıtlar:


2
bool(){ return "$((!${#1}))"; }

if bool "$var"
then : do true
else : do false

Açıkçası olmasa [ -n "$var" ]da, daha kısa olsa da , yukarıdaki işe yaraması için null değil ama herhangi bir şeye bir değişken ayarlayın .

Genel olarak bir komut dosyası bir ortam değişkenini doğru veya yanlış olarak yorumladığında, herhangi bir değeri hiç doğru olarak (ve bazen söz konusu değeri bazı seçenekleri yapılandırmak için kullanır) ya da başka bir null değerini false olarak yorumlar.

Yukarıdaki !not, ilk bağımsız değişkeninin len'in boolean değerini döndürür - bağımsız değişken 0 dışında bir sayıda karakter içeriyorsa 0 döndürür, aksi takdirde hiç karakter yoksa 1 döndürür. Bu [ -n "$var" ], temel olarak gerçekleştirebileceğiniz aynı testtir. , ancak sadece adlı küçük bir işlevde sarar bool().

Bir bayrak değişkeni bu şekilde çalışır. Örneğin:

[ -d "$dir" ] || dir=

Bir komut dosyasının diğer bölümlerinin $dirkullanışlılığını ölçmek için herhangi bir değer araması gerektiğinde. Bu aynı zamanda parametre ikamesi söz konusu olduğunda da kullanışlıdır - parametreler boş veya ayarlanmamış olanlar için doldurmak için varsayılan değerlere genişletilebilir, ancak aksi takdirde önceden belirlenmiş bir değere genişler ...

for set in yes ''
do echo "${set:-unset or null}"
done

... yazdıracak ...

yes
unset or null

Tabii ki, bunun tersini yapmak da mümkündür, :+ancak bu size yalnızca önceden ayarlanmış bir varsayılan veya hiçbir şey veremezken, yukarıdaki form size bir değer veya varsayılan bir değer verebilir.

Üç seçenekle ilgili olarak - bunu nasıl uygulamayı seçtiğinize bağlı olarak herhangi biri işe yarayabilir. İşlevin dönüşü kendi kendini sınamadır, ancak bu dönüşün herhangi bir nedenle kaydedilmesi gerekiyorsa, bir değişkene konulması gerekir. Kullanım durumuna bağlıdır - bir testi bir kez değerlendirmek ve türünü yapmak istediğiniz boole değeri mi? Eğer öyleyse, fonksiyonu yapın, muhtemelen diğer ikisinden biri gereklidir.


1
Soruma cevap verdiğini sanmıyorum. Booleans'in bir kabuk betiğinde nasıl kullanılabileceğini sormuyorum, ama en yaygın olanı ve başka bir kullanıcı tarafından beklenen bir yol. Sorum net değilse, düzenlemekten memnuniyet duyarım. Ayrıca cevabınızın ne yaptığına dair kısa bir açıklama da iyi olur. Teşekkür ederim.
Minix

@Minix Daha iyi misin?
mikeserv

Genellikle bir değişkene trueveya falsebir değişkene if $variable; then ...
atarım

@wurtel - varsayılan olarak kullanılır $IFS- ve var'ın değeri herhangi bir kullanıcı girdisi içeriyorsa, o zaman da iyi şanslar. Değerin başlaması bilinmiyorsa, test etmek için çok az ihtiyaç vardır. if ${var:+":"} false; thenBoole null / null olmayan değerlerle çalışırken daha güvenli yapabilirsiniz . Ancak bu nadiren daha yararlıdır[ -n "$var" ] &&
mikeserv

Eğer benim komut dosyası ile başlatmak variable=falseve sonra ne olursa olsun (C değişken bir kullanırken) gibi herhangi bir koşula göre doğru olarak ayarlanırsa, o zaman hiçbir sorun var, Değişen IFS değerleri ve rastgele değişken değerleri vb saplantı nedir Ne olursa olsun .. .
wurtel

4

Gelen bashher değişkenin aslında bir dize (veya bir dizi ya da bir fonksiyon, fakat düzenli değişkenler burada yaklaşık edelim mesaj).

Koşullar, test komutlarının dönüş değerlerine göre ayrıştırılır - dönüş değeri bir değişken değildir, bir çıkış durumudur. Bunu değerlendirdiğinizde if [ ... ]veya if [[ ]]veya if grep somethingherhangi bir şey yaptığınızda, dönüş değeri 0 (dize 0 değil, çıkış durumu 0 = başarı) true anlamına gelir ve geri kalanı false anlamına gelir (yani, derlenmiş programlama dillerinde alışkın olduğunuzun tam tersi, ancak başarılı olmanın bir yolu ve başarısız olmanın birçok yolu olduğu ve yürütmenin beklenen sonucu genellikle başarılı olduğu için, hiçbir şey yanlış gitmezse en yaygın varsayılan sonuç olarak 0 kullanılır). Bu çok kullanışlıdır, çünkü herhangi bir ikili test olarak kullanılabilir - başarısız olursa yanlıştır, aksi takdirde doğrudur.

trueve falseprogramlar (genellikle yerleşikler tarafından geçersiz kılınan) sadece hiçbir şey yapmayan yararlı küçük programlardır - hiçbir şey trueyapmayı başarmaz ve 0 ile çıkar, falsehiçbir şey yapmayı denemez ve "başarısız olur", 1 ile çıkar. Anlamsız geliyor ama komut dosyası oluşturmak için çok kullanışlıdır.

Doğruluktan nasıl geçileceği konusunda, size kalmış. Gerçeklik ve kullanım için sadece "y" veya "evet" kullanmak oldukça yaygındır if [ x"$variable" = x"yes" ](kukla dizeyi ekler, xçünkü $variablesıfır uzunluk olursa, if [ = "yes" ]ayrıştırılmayan sahte bir komut oluşturmaktan korur ). Ayrıca yanlış için boş bir dize kullanmak [ -z "$variable ]ve sıfır uzunluğunda (veya -nsıfırdan farklı olup olmadığını) test etmek için de yararlı olabilir .

Her neyse, aslında boolean değerlerin içinden geçmesi oldukça nadirdir bash- sadece exitbaşarısızlık durumunda veya yararlı bir sonuç döndürmek (veya bir şey ters giderse sıfır ve boş dizeyi test etmek) çok daha yaygındır ve çoğu durumda doğrudan çıkış durumundan arıza olup olmadığını test edin.


Sizin durumunuzda, başka bir komut gibi davranacak bir işlev istiyorsunuz (bu nedenle, başarıya 0 döndürün), böylece son seçeneğiniz doğru seçim gibi görünüyor.

Ayrıca, returnifadeye bile ihtiyacınız olmayabilir . İşlev yeterince basitse, işlevdeki son yürütülen komutun durumunu döndürmesi gerçeğini kullanabilirsiniz. Böylece fonksiyonunuz

drive_xyz_available() {
   [ -e /dev/disk/by-uuid/whatever ]
}

bir aygıt düğümünün varlığını test ediyorsanız (veya /proc/mountstakılı olup olmadığını kontrol etmek için grep ?).


Bu çok güzel bir özet, yazmak için zaman ayırdığınız için teşekkür ederiz. Son paragrafınızdan, drive_xyz_available()en yaygın seçenek olarak değerlendireceğinizi çıkarabilir miyim ?
Minix

Yaygın y = truedurum için bazı örnekler verebilir misiniz ? Deneyimlerime göre, çoğu paket betiği, en azından yorumlanmış ortam değişkenleri söz konusu olduğunda, bunu doğru olarak değerlendirmek için boş olmayan herhangi bir değeri test eder. Aksi takdirde mermi arabalarını tamamen görmezden gelirler.
mikeserv

3
ifDeğişken belirtilmişse , test için kukla dize gerekli değildir; if [ "$variable" = "yes" ]$ değişkeni ayarlanmamış olsa bile iyi çalışır.
daniel kullmann

-2

Temelde 0 olmayan herhangi bir sayı doğrudur ve 0 yanlıştır. Farklı türdeki hataları tanımlamak için bir komut dosyasının veya başka bir sayının başarılı bir şekilde sona erdirilmesi için değerleri 0 olarak döndürme nedeni.

$? önceki komutun / yürütülebilir dosyanın çıkış kodunu döndürür, 0 başarılı olur ve döndürülen hata başka bir sayıdır.

Bu yüzden doğru / yanlış için bu yöntemi kullanırdım. if (( ! $? ));then OK;else NOOK;fi


Son seçenek için bir tane yazacağım. Teşekkür ederim.
Minix

5
Sıfır olmayan bir sayı aslında yanlış ve sıfır doğrudur. Sadece çıkışında bakmak true; echo $?ve false; echo $?.
Ruslan

@Ruslan. Komutumun çıktısını kontrol ettiniz mi? Sanırım yapmadın, aksi takdirde ne yaptığını söylemezdin. 0 yanlıştır, başka herhangi bir sayı doğrudur, !sonucun DOĞRU olması için reddetme nedeni Bir komutun sonucu, doğru şekilde tamamlandığında 0'dır; bu, 0'ın doğru olduğu anlamına gelmez. Sözcük true0 olabilir, ancak ifkoşulun gösterdiği gibi 0 asla doğru değildir .
YoMismo

Yani C / C ++, söyleyerek aynı şey 0olduğunu true, çünkü if(!x){True();}else{False();}arayacak True()zaman x==0. Ancak doğru kontrol değil !x, daha doğrusu olurdu !!x.
Ruslan

Waaaaaaay yanlışsın. Ben sadece ne (hangi sırayla ne yazdığından bahsetmiyorum) ifsadece (bash, ksh veya tsh veya .... gibi) C / C ++ a 0 YANLIŞ, diğer sayı TRUE'dur, aşağıdaki bağlantıda okuyabileceğiniz gibi, C'nin ilk uygulamalarında boole türü sağlanmadı; 0, FALSE ve 1 TRUE olan ints olarak tanımlandı . en.wikipedia.org/wiki/Boolean_data_type .
YoMismo
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.