it-swarm-id.com

Bagaimana saya bisa menetapkan output dari perintah ke variabel Shell?

Saya ingin menetapkan hasil ekspresi ke variabel dan menyatukannya dengan string, lalu menggemakannya. Inilah yang saya punya:

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

Tapi itu menghasilkan:

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

Jadi, sepertinya itu tidak ditugaskan $thefile, dan sedang dicetak saat dijalankan.

82
Nathan G.

Tugas Shell adalah satu kata, tanpa spasi setelah tanda sama dengan. Jadi apa yang Anda tulis memberikan nilai kosong ke thefile; lebih jauh, karena tugas dikelompokkan dengan perintah, itu membuat thefile variabel lingkungan dan tugas adalah lokal untuk perintah tertentu, yaitu hanya panggilan ke ls melihat nilai yang ditugaskan.

Anda ingin menangkap output dari suatu perintah, jadi Anda perlu menggunakan substitusi perintah :

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

(Beberapa literatur menunjukkan sintaks alternatif thefile=`ls …`; Sintaks backquote setara dengan sintaks dolar-kurung kecuali bahwa mengutip di dalam backquotes kadang-kadang aneh, jadi gunakan $(…).)

Keterangan lain tentang skrip Anda:

  • Menggabungkan -t (Urutkan berdasarkan waktu) dengan -U (Jangan urutkan) tidak masuk akal; cukup gunakan -t.
  • Daripada menggunakan grep untuk mencocokkan tangkapan layar, lebih jelas untuk meneruskan wildcard ke ls dan menggunakan head untuk mengambil file pertama:

    thefile=$(ls -t *"Screen Shot"* | head -n 1)
    
  • Biasanya ide buruk untuk menguraikan output ls . Ini bisa gagal sangat buruk jika Anda memiliki nama file dengan karakter yang tidak dapat dicetak. Namun, menyortir file berdasarkan tanggal sulit tanpa ls, jadi ini solusi yang dapat diterima jika Anda tahu Anda tidak akan memiliki karakter yang tidak patut atau garis miring terbalik dalam nama file.

  • Selalu gunakan tanda kutip ganda di sekitar substitusi variabel , yaitu di sini menulis

    echo "Most recent screenshot is: $thefile"
    

    Tanpa tanda kutip ganda, nilai variabel diekspansi ulang, yang akan menyebabkan masalah jika berisi spasi putih atau karakter khusus lainnya.

  • Anda tidak perlu titik koma di akhir baris. Mereka mubazir tetapi tidak berbahaya.
  • Dalam skrip Shell, sering kali merupakan ide bagus untuk menyertakan set -e . Ini memberi tahu Shell untuk keluar jika ada perintah yang gagal (dengan mengembalikan status bukan nol).

Jika Anda memiliki GNU find (khususnya jika Anda menjalankan Linux atau Cygwin yang tidak tertanam), ada pendekatan lain untuk menemukan file terbaru: minta find daftar file dan tanggalnya, dan gunakan sort dan tail untuk mengekstrak file termuda.

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

Jika Anda ingin menulis skrip ini di zsh daripada bash, ada cara yang jauh lebih mudah untuk menangkap file terbaru, karena zsh memiliki glob qualifiers yang memungkinkan kecocokan wildcard tidak hanya pada nama tetapi juga pada file metadata. Bagian (om[1]) Setelah pola adalah kualifikasi glob; om mengurutkan kecocokan dengan bertambahnya usia (mis. pada waktu modifikasi, yang terbaru lebih dulu) dan [1] mengekstrak kecocokan pertama saja. Seluruh kecocokan harus dalam tanda kurung karena secara teknis ini adalah array, karena globbing mengembalikan daftar file, bahkan jika [1] Berarti bahwa dalam kasus khusus ini daftar berisi (paling banyak) satu file.

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

Jika Anda ingin melakukannya dengan multiline/beberapa perintah/s maka Anda dapat melakukan ini:

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

Atau:

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

Contoh:

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

Keluaran:

first
second
third
4
Jahid