Mengevaluasi string dalam skrip shell

8

Saya mengikuti panduan skrip bash shell ini:

Di bagian Perbandingan Numerik, ia mengutip sebuah contoh:

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

Apa yang tampaknya terjadi di atas adalah kita menyimpan serangkaian perintah dalam variabel bash dan kemudian kita memanggil gema pada variabel. Apa yang tampaknya terjadi adalah string dievaluasi dan perintah wc dieksekusi dan mengembalikan jumlah baris ke terminal pengendali.

Ok, jadi saya meluncurkan terminal saya di Ubuntu 12.04 dan mencoba sesuatu yang serupa:

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

Tunggu sebentar, itu tidak mengevaluasi string dan mengembalikan jumlah baris. Itu baru saja menggemakan string kembali ke terminal. Mengapa saya mendapatkan hasil yang berbeda?

JohnMerlino
sumber
Perhatikan bahwa num tidak pernah diberi string wc -l work.txt, melainkan diberi nomor 201.
ignis
Sumber terkait: 3.5.4 Pergantian Perintah dalam manual referensi Bash .
Eliah Kagan

Jawaban:

2

Anda perlu menggunakan backticks untuk mengevaluasi ekspresi.

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

Jika Anda hanya ingin melihat "1" di output, gunakan perintah

$ num=`cat sample.txt | wc -l`
$ echo $num
1

Dan juga berfungsi:

$ num=`wc -l < sample.txt`
$ echo $num
1

Untuk informasi tambahan, lihat Perbedaan antara doublequotes "", singlequotes '' dan backticks ´ ´ pada commandline?

Danatela
sumber
Adakah ide mengapa saya mendapatkan '1 sample.txt' dan bukan hanya angka '1'?
JohnMerlino
Begitulah cara wckerja perintah. Coba cat sample.txt | wc -l.
Danatela
wc -l menampilkan jumlah baris yang ada dalam file bersama dengan nama filenya.
Avinash Raj
5

Harap perhatikan simbol itu:

'

Kutipan tunggal

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

dan

`

Backquote

   Command substitution allows the output of a command to replace the com
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

Jadi Backquote mengembalikan hasil perintah ke Output Standar. Itulah mengapa

`wc -l sample.txt`

mengembalikan hasil perintah, sementara

'wc -l sample.txt'

cukup kembalikan "wc -l sample.txt" sebagai string biasa

Pertimbangkan untuk melakukan ini sebagai contoh:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

Dan sekarang gema ketiga variabel:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts
c0rp
sumber
4

Jika Anda ingin menangkap output dari suatu perintah dalam variabel, Anda harus menggunakan backticks ``atau menyertakan perintah di $():

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

Perhatikan bahwa string sebenarnya dievaluasi pada saat deklarasi variabel, bukan ketika Anda menggemakannya. Perintah ini sebenarnya dijalankan di dalam $()atau backticks dan output dari perintah itu disimpan sebagai nilai variabel.

Secara umum, Anda harus selalu menggunakan $()bukannya backticks yang sudah usang dan hanya ada untuk alasan kompatibilitas dan jauh lebih terbatas. Anda tidak bisa, misalnya, perintah sarang dalam backticks tetapi Anda bisa dengan $():

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

Lihat utas ini di U&L untuk beberapa perincian lebih lanjut mengapa ``harus dihindari.

terdon
sumber
1
Saya setuju script harus memilih $( )untuk ` `. Tapi seperti wag mengatakan , backquotes lakukan sarang. echo $(date -d $(echo yesterday))menjadi echo `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday)))menjadi echo `echo \`date -d \\\`echo yesterday\\\`\``. Saya mengatakan ini tidak membantah tesis Anda tetapi untuk memperkuatnya : lolos dari backquotes internal membuat ` `sintaksis lebih kuat daripada yang sering diakui, tetapi perlakuan khusus \aneh, mengejutkan, dan sulit untuk dipikirkan . Dengan $( )apa yang Anda lihat biasanya apa yang Anda dapatkan.
Eliah Kagan