Zmienna nie jest analizowana jako ciąg

10

Problem

Próbowałem wyodrębnić poziom sygnału dla Wi-Fi w następujący sposób, w skrypcie bash (cytaty wydają się nie mieć znaczenia):

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

Jeśli echo $stringotrzymam to, czego oczekuję:

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

Ale jeśli spróbuję uzyskać podłańcuch, echo ${string:5}zwraca to samo.


Debugowanie:

Jeśli wkleję dane wyjściowe wconfig wlan0 | grep -I Signalbezpośrednio do zmiennej: string="Link Quality=63/70 Signal level=-47dBm"wtedy wszystko działa zgodnie z oczekiwaniami.

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

Pytanie: Według Internetu wszystkie zmienne bash są przechowywane jako ciągi znaków. Dlatego wynik debugowania powinien być taki sam jak mój pierwotny problem. Czy istnieje jakiś powód, dla którego nie jest on analizowany jako tekst w pierwotnym problemie?

Ion Sme
źródło

Odpowiedzi:

15

Jest tak, ponieważ echo $stringnie drukuje się po prostu wartości string; najpierw wykonuje operację split + glob - jedną z konsekwencji jest unikanie wiodących białych znaków:

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

natomiast

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

Widzimy, że na początku jest sekwencja znaków spacji $string- w rzeczywistości jest ich więcej niż 5, więc usunięcie 5 nadal pozostawia ciąg z wiodącymi białymi ${string:5}spacjami, co pomija także niecytowane rozszerzenie podłańcucha ( ):

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

Dodatkowa dyskusja patrz:

steeldriver
źródło
4
Tl; dr zawsze cytuj swoje zmienne
gronostaj
6

Działa to na moim komputerze:

$ 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
  • Na komputerze zastąpić wlp60s0z wlan0.
  • Zauważ, że używa to Ubuntu 16.04 i Ubuntu 19.04, gdzie jest spacja między 42a dBm. Jako takie cutpolecenie otrzymuje polecenie wydrukowania pól # 4 i # 5. W twoim pytaniu nie ma miejsca, więc nie jestem pewien, jakiej wersji używasz.

Możesz również użyć:

$ echo $string | cut -d'=' -f3
-42 dBm
  • W takim przypadku cutzaleca się stosowanie =jako ogranicznika pola.

Jeśli chcesz użyć ${string...}poprawnej składni to:

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

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

Każda metoda będzie działać, aby pobrać podciąg po ostatniej =. Oryginalna metoda 5twojego pytania nie rozumiem, jak to może działać.

WinEunuuchs2Unix
źródło