it-swarm-tr.com

Bir komutun çıktısını Shell değişkenine nasıl atayabilirim?

Bir ifadenin sonucunu bir değişkene atamak ve bir dize ile birleştirmek ve sonra yankılamak istiyorum. İşte sahip olduğum şeyler:

#!/bin/bash
cd ~/Desktop;
thefile= ls -t -U | grep -m 1 "Screen Shot";
echo "Most recent screenshot is: "$thefile;

Ancak bu çıktı:

Screen Shot 2011-07-03 at 1.55.43 PM.png
Most recent screenshot is: 

Yani, $thefile ve yürütülürken yazdırılıyor.

82
Nathan G.

Kabuk ataması, eşittir işaretinden sonra boşluk bırakmayan tek bir Word'dür. Böylece yazdıklarınız thefile 'a boş bir değer atar; ayrıca, atama bir komutla gruplandığından, thefile bir ortam değişkeni yapar ve atama bu komut için yereldir, yani yalnızca ls çağrısı atanan değeri görür.

Bir komutun çıktısını yakalamak istiyorsunuz, bu yüzden komut yerine koyma kullanmanız gerekir:

thefile=$(ls -t -U | grep -m 1 "Screen Shot")

(Bazı literatür alternatif bir sözdizimi gösterir thefile=`ls …`; Arka tırnak sözdizimi dolar-parantez sözdizimine eşdeğerdir, ancak arka tırnak içinde alıntı yapmak bazen gariptir, bu nedenle $(…) kullanın.)

Senaryonuzla ilgili diğer açıklamalar:

  • -t (Zamana göre sırala) ile -U (Sıralamayın) ile birleştirmek anlamlı değildir; sadece -t kullanın.
  • Ekran görüntülerini eşleştirmek için grep kullanmak yerine, joker karakteri ls 'e geçirmek ve head kullanmak ilk dosyayı yakalamak için daha açıktır:

    thefile=$(ls -t *"Screen Shot"* | head -n 1)
    
  • Genellikle bir ls çıktısını ayrıştırmak kötü bir fikirdir . Yazdırılamayan karakterlere sahip dosya adlarınız varsa bu oldukça kötü bir şekilde başarısız olabilir. Ancak dosyaları ls olmadan tarihe göre sıralamak zordur, bu nedenle dosya adlarında yazdırılamaz karakterler veya ters eğik çizgiler olmayacağını biliyorsanız kabul edilebilir bir çözümdür.

  • Değişken ikamelerinde her zaman çift tırnak kullanın , yani buraya yazın

    echo "Most recent screenshot is: $thefile"
    

    Çift tırnak işaretleri olmadan, değişkenin değeri genişletilir ve bu boşluk veya başka özel karakterler içeriyorsa soruna neden olur.

  • Bir satırın sonunda noktalı virgül gerekmez. Gereksiz ama zararsızdırlar.
  • Bir Shell betiğinde, set -e eklemek iyi bir fikirdir. Bu, Kabuk'tan herhangi bir komutun başarısız olması durumunda (sıfır dışında bir durum döndürerek) çıkmasını bildirir.

GNU find (özellikle gömülü olmayan bir Linux veya Cygwin çalıştırıyorsanız) varsa, en son dosyayı bulmak için başka bir yaklaşım daha vardır: find dosyaları listele tarihlerini girin ve en küçük dosyayı ayıklamak için sort ve tail kullanın.

thefile=$(find -maxdepth 1 -type f -name "*Screen Shot*" -printf "%[email protected] %p" |
          sort -k 1n | tail -n 1)

Bu komut dosyasını bash yerine zsh'de yazmak istiyorsanız, en yeni dosyayı yakalamanın çok daha kolay bir yolu vardır, çünkü zsh, yalnızca adlarda değil dosyada da joker karakter eşleşmelerine izin veren glob elemeleri değerine sahiptir. meta. Kalıptan sonraki (om[1]) Kısmı glob niteleyicileri; om karşılaşmaları yaşları arttırarak sıralar (yani değişiklik zamanına göre, en yenisi ilk sırada) ve [1] sadece ilk maçı çıkarır. [1] Bu özel durumda listenin (en fazla) bir dosya içerdiği anlamına gelse bile, globbing bir dosya listesi döndürdüğünden, tüm eşleşmenin parantez içinde olması gerekir.

#!/bin/zsh
set -e
cd ~/Desktop
thefile=(*"Screen Shot"*(om[1]))
echo "Most recent screenshot is: $thefile"

Çok satırlı/çoklu komut (lar) ile yapmak istiyorsanız, bunu yapabilirsiniz:

output=$( bash <<EOF
#multiline/multiple command/s
EOF
)

Veya:

output=$(
#multiline/multiple command/s
)

Misal:

#!/bin/bash
output="$( bash <<EOF
echo first
echo second
echo third
EOF
)"
echo "$output"

Çıktı:

first
second
third
4
Jahid