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


76

Bir ifadenin sonucunu bir değişkene atamak ve onu bir dize ile birleştirmek, sonra da eko yapmak istiyorum. İşte elimde ne var:

#!/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, atanmamış gibi görünüyor $thefileve idam edildiği gibi basılıyor.


Related:
İçinden

Yanıtlar:


108

Bir kabuk ataması, eşittir işaretinden sonra boşluk bırakmayan tek bir kelimedir. Öyleyse yazdıklarına boş bir değer atar thefile; ayrıca, atama bir komutla gruplandırıldığından, thefilebir ortam değişkenini yapar ve atama söz konusu komut için yereldir, yani yalnızca lsatanan değeri gören çağrı .

Bir komutun çıktısını yakalamak istiyorsunuz, bu nedenle komut değiştirme kullanmanız gerekir :

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

(Bazı literatür alternatif bir sözdizimi gösterir thefile=`ls …`; backquote sözdizimi, backquotes içinde alıntı yapmak bazen garip olduğu için dolar-parantez sözdizimine eşdeğerdir, bu yüzden sadece kullanın $(…).)

Komut dosyanızla ilgili diğer açıklamalar:

  • -t(Zamana göre sırala) ile -U(sıralama yapma ) birleştirmek anlamlı değildir; Sadece kullan -t.
  • grepEkran görüntülerini eşleştirmek için kullanmak yerine , bir joker karakter iletmek ve ilk dosyayı yakalamak için lskullanmak daha açıktır head:

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

  • Her zaman değişken değişkenlerin etrafında çift tırnak kullanın , yani buraya yazın

    echo "Most recent screenshot is: $thefile"

    Çift tırnak işareti olmadan, değişken değeri yeniden genişletilir; bu da boşluk veya diğer özel karakterler içeriyorsa sorun çıkarır.

  • Satır sonunda noktalı virgül gerekmez. Gereksiz ama zararsızlar.
  • Bir kabuk betiğinde, dahil etmek genellikle iyi bir fikirdir set -e. Bu, herhangi bir komutun başarısız olması durumunda kabuğa çıkılmasını söyler (sıfır olmayan bir durum döndürerek).

GNU bulmanız varsa (özellikle gömülü olmayan Linux veya Cygwin kullanıyorsanız), en yeni dosyayı bulmak için başka bir yaklaşım daha vardır: finddosyaları ve tarihlerini listele sortve tailen genç dosyayı çıkartmak için kullan ve kullan .

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

Bu betiği bash yerine zsh ile yazmak istiyorsanız, en yeni dosyayı yakalamanın daha kolay bir yolu vardır, çünkü zsh, joker karakterin yalnızca adlarda değil, dosya meta verilerinde de eşleşmesine izin veren glob niteleyicilere sahiptir. (om[1])Desenin sonraki kısım Glob elemeleri olduğu; omyaş değiştirerek eşleşmeleri sıralar (örneğin, değişiklik zamanına göre, önce en yenisi) ve [1]yalnızca ilk eşleşmeyi çıkarır. Tüm eşlemenin parantez içinde olması gerekir, çünkü teknik olarak bir dizidir, çünkü globbing bir listede bir liste döndürür, çünkü [1]bu özel durumda listede (en fazla) bir dosya içeriyorsa bile .

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

7
Vaov! Beklediğimden daha fazla bilgi. Cevabınız için birçok kez teşekkür ederiz; Buna harcadığın tüm çabayı gerçekten takdir ediyorum! Az önce bana gerçekten, gerçekten öğrenecek çok şeyim olduğunu gösterdin. Bash hakkında bir kitap almaya gidiyorum: P.
Nathan G.

3
Buna kesin cevap diyeceğim ! :)
alex,

4

Çok satırlı / çoklu komut / s ile yapmak istiyorsanız o zaman bunu yapabilirsiniz:

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

Veya:

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

Örnek:

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

Çıktı:

first
second
third

Bu güzel bir cevap. değişkeni komutun bir parçası olarak belirtebileceğim bir yol var mı? örneğinoutput=$(echo $someVariable)
Zach Smith
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.