Let, expr ve $ [] arasındaki fark


23

Aradaki farkın tam olarak ne olduğunu bilmek istiyorum.

a=$[1+1]
a=$((1+1))
let a=1+1
a=$(expr 1 + 1 )

Tüm 4 a değişkenini 2 ile atar, ancak fark nedir?

Şimdiye kadar öğrendiklerime göre, expr daha yavaş, çünkü gerçek bir kabuk yerleşimi değil. Fakat bundan başka bir şey değil.

Yanıtlar:


25

Bunların hepsi aritmetik ile ilgilidir, ancak farklı şekillerde ve değişken farklı araçlarla yaratılır. Bunlardan bazıları bashkabuğa özgü , bazıları ise kabuğuna özgü değil.

  • $((...))kabukları ve tipik olan aritmetik genişleme denir . Bu, basit tamsayılı aritmetik işlem yapılmasına izin verir ; Gibi ifadenin sonucu, ifadesini değiştirir olacaktıbashkshecho $((1+1))echo 2
  • ((...))Aritmetik değerlendirme olarak adlandırılır ve bir ifadesi if ((...)); thenveya while ((...)) ; doifadeleri olarak kullanılabilir . Aritmetik genişleme genişlemesi $((..)), işlemin çıktısının yerini alır ve i=$((i+1))koşullu ifadelerde olduğu gibi değişken atamak için kullanılabilir, ancak koşullu ifadelerde kullanılamaz.
  • $[...] kullanımdan kaldırılan aritmetik genişlemenin eski sözdizimidir. Ayrıca bakınız . Bu muhtemelen eski bashkomut dosyalarının bozulmaması için saklandı . Bu işe yaramadı ksh93, bu yüzden benim tahminim bu sözdiziminin bash özgüdür. NOT : Burada boşluklar çok önemlidir; $[1+1]gibi şeylerle karıştırmayın [ $a -eq $b ]. [Boşluklarla olarak bilinen testkomuta ve genellikle karar verme yerlerinde görüyoruz. Davranış ve amaç bakımından çok farklı.
  • letbasit aritmetik değerlendirme ile değişken yaratmaya izin veren bir bashve kshanahtar kelimedir. Orada bir dize atamaya çalışırsanız, let a="hello world"bir sözdizimi hatası alırsınız. Çalışıyor bashve ksh93.
  • $(...)komut yerine, kelimenin tam anlamıyla bir komutun çıktısını alır ve bir değişkene atarsınız. Buradaki expremriniz, konumsal argümanlar alan expr arg1 arg2 arg3, yani boşluklar önemlidir. Tamsayı aritmetiği için küçük bir komut satırı hesap makinesi gibi artı bazı doğru / yanlış ve regex türü şeyler gibi. Bu kabuk nötr bir komuttur.

Ayrıca aritmetik genişleme ve komut ikamesi tarafından belirtilen dikkati çekiyor POSIX standardı ise letve $[...]değillerdir.


1
((...))aslında atamaları için kullanılabilir bash, kshve zsh: n=10; ((n+=10)); echo $n20 ve yazdırır ((x=1)); echo $x1. baskılar
Alexej Magura

1
@Alexej Teşekkürler. Yanıt güncellendi, bu bölüm kaldırıldı
Sergiy Kolodyazhnyy

11
  • letkomut aritmetik değerlendirme yapar ve yerleşik bir kabuktur.

    • Bu komutu çalıştırın ve hiçbir şey alamadım (sadece değerlendirir):

      let 1+2
  • $(( ))aritmetik genişleme yapmak için kullanılır : burada oku

    • Bunu çalıştırdığınızda bir hata alırsınız (genişleme nedeniyle):

      $((1+2))
  • $[ ] aritmetik genişlemenin eski sözdizimi:

    Eski biçim $ [expression] kullanımdan kaldırıldı ve bash yaklaşırken kaldırılacak. Bash Man Page

  • expr İkili bir komuttur, eğer bir komut alt öğesi içinde aritmetik genişleme yapmak istiyorsanız, onu kullanabilirsiniz:

    echo $(expr 1 + 2) 
    echo `expr 1 + 2`

4

Yukarıdaki cevaplardan bazıları özellikle bahsettiğinden ksh93, kayan nokta matematiği yapabileceğini belirtmeye değer, örneğin:

$ print $((1.0/3)) 
0.333333333333333333

Çıktının hassasiyetini printf ile kontrol edebilirsiniz, örneğin:

$ printf "%.4f\n" $((1.0/3))
0.3333

En az bir argüman yukarıdaki gibi kayan nokta sayısı olarak belirtilmelidir. Her ikisi de tamsayı olarak belirtilmişse, yalnızca tamsayı matematik işlemi yapılır, örneğin:

$ print $((1/3))  
0

Harici bir komut çağırmaktan kaçınabileceğinizden, bir kabuk komut dosyasında kayan nokta matematiğine ihtiyacınız olduğunda bu yardımcı olabilir.


Bana bir cevap göndermek ilginizi çekebilir bana bash betiğinde kesir / ondalık kullanabilir miyim? Başlığa rağmen, bağlamın diğer Bourne tarzı mermilerin konuyla ilgili olduğunu açıkça ortaya koyduğunu ve bu yüzden bir zshcevap gönderdiğimi düşünüyorum . Yana kshve bashbirine daha (genel olarak) birbirine daha benzer zsh, bir geliyor bana kh93bu sorunun tabanlı cevap oldukça yararlı olabilir.
Eliah Kagan

1

letcronda çalışmıyor. Bunun letkendi ortamına sahip olmasından kaynaklandığını düşünüyorum . POSIX'ten $((...))beri kullanın . Örneğin,

let x=1+2
echo x=$x

cron'da kabuktan çalıştırıldığında "x =", fakat "x = 3" olur.

x=$((1+2))
echo x=$x

her durumda "x = 3" ile sonuçlanır.

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.