Variabel tidak diurai sebagai string

10

Masalah

Saya mencoba mengekstrak level sinyal untuk wifi dengan cara berikut, dalam skrip bash (kutipan tampaknya tidak membuat perbedaan):

string="$(iwconfig wlan0 | grep -I Signal)"

Jika saya echo $string, saya mendapatkan apa yang saya harapkan:

Link Quality=63/70 Signal level=-47dBm

Tetapi jika saya mencoba untuk mendapatkan substring echo ${string:5},, ia mengembalikan hal yang sama.


Debuging:

Jika saya menempelkan output wconfig wlan0 | grep -I Signallangsung ke variabel: string="Link Quality=63/70 Signal level=-47dBm"maka semuanya berfungsi seperti yang diharapkan.

echo $string 
# Link Quality=63/70 Signal level=-47dBm
echo ${string:5}
# Quality=63/70 Signal level=-47dBm

Pertanyaan: Menurut internet, semua variabel bash disimpan sebagai string karakter. Jadi, hasil debug seharusnya sama dengan masalah asli saya. Apakah ada alasan mengapa itu tidak diuraikan sebagai teks dalam masalah asli?

Ion Sme
sumber

Jawaban:

15

Ini karena echo $stringtidak hanya mencetak nilai string; pertama kali melakukan operasi split + glob - salah satu konsekuensi di antaranya adalah bahwa spasi putih terdepan dihilangkan:

$ string=$(iwconfig wls1 | grep Signal)
$ echo $string
Link Quality=38/70 Signal level=-72 dBm

sedangkan

$ echo "$string"
          Link Quality=38/70  Signal level=-72 dBm  

Kita dapat melihat bahwa ada urutan karakter spasi putih di awal $string- sebenarnya ada lebih dari 5, jadi menghapus 5 masih meninggalkan string dengan spasi putih terkemuka, yang merupakan perluasan substring yang tidak ${string:5}dikutip ( ) juga elides:

$ echo "${string:5}"
     Link Quality=38/70  Signal level=-72 dBm  
$ echo ${string:5}
Link Quality=38/70 Signal level=-72 dBm

Untuk diskusi tambahan, lihat:

Steeldriver
sumber
4
Tl; dr selalu mengutip variabel Anda
gronostaj
6

Ini bekerja pada mesin saya:

$ string="$(iwconfig wlp60s0 | grep -I Signal)"
$ echo $string
Link Quality=68/70 Signal level=-42 dBm
$ echo $string | cut -d' ' -f4,5
level=-42 dBm
  • Untuk mesin Anda ganti wlp60s0dengan wlan0.
  • Perhatikan ini menggunakan Ubuntu 16.04 dan Ubuntu 19.04 di mana ada ruang antara 42dan dBm. Karena itu cutperintah ini diperintahkan untuk mencetak bidang # 4 dan # 5. Dalam pertanyaan Anda tidak ada ruang jadi saya tidak yakin versi apa yang Anda gunakan.

Anda juga bisa menggunakan:

$ echo $string | cut -d'=' -f3
-42 dBm
  • Dalam hal cutini disuruh menggunakan =sebagai pembatas lapangan.

Jika Anda ingin menggunakan ${string...}sintaks yang benar adalah:

$ echo ${string##*=}
-38 dBm

$ echo "${string##*=}"
-38 dBm  

Metode mana pun akan bekerja untuk mengambil substring setelah yang terakhir =. Metode asli 5dalam pertanyaan Anda, saya tidak mengerti bagaimana cara kerjanya.

WinEunuuchs2Unix
sumber