Variable wird nicht als Zeichenfolge analysiert

10

Problem

Ich habe versucht, den Signalpegel für WLAN auf folgende Weise in einem Bash-Skript zu extrahieren (Anführungszeichen scheinen keinen Unterschied zu machen):

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

Wenn ich echo $stringbekomme, bekomme ich was ich erwarte:

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

Aber wenn ich versuche, einen Teilstring zu bekommen echo ${string:5}, gibt er dasselbe zurück.


Debuggen:

Wenn ich die Ausgabe von wconfig wlan0 | grep -I Signaldirekt in die Variable string="Link Quality=63/70 Signal level=-47dBm"einfüge, funktioniert alles wie erwartet.

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

Frage: Laut Internet werden alle Bash-Variablen als Zeichenfolgen gespeichert. Daher sollte das Debugging-Ergebnis das gleiche sein wie mein ursprüngliches Problem. Gibt es einen Grund, warum es im ursprünglichen Problem nicht als Text analysiert wird?

Ion Sme
quelle

Antworten:

15

Dies liegt daran, echo $stringdass nicht einfach der Wert von gedruckt wird string. Zunächst wird eine Split + Glob- Operation ausgeführt. Eine der Konsequenzen ist, dass führende Leerzeichen entfernt werden:

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

wohingegen

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

Wir können sehen, dass es zu Beginn eine Folge von Leerzeichen $stringgibt - tatsächlich gibt es mehr als 5, so dass beim Entfernen von 5 immer noch eine Zeichenfolge mit führenden Leerzeichen ${string:5}verbleibt , die durch eine nicht zitierte Teilzeichenfolgenerweiterung ( ) ebenfalls entfernt wird:

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

Weitere Informationen finden Sie unter:

Steeldriver
quelle
4
Tl; dr zitieren Sie immer Ihre Variablen
gronostaj
6

Das funktioniert auf meinem Computer:

$ 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
  • Für Ihre Maschine ersetzen wlp60s0durch wlan0.
  • Beachten Sie , dass hier Ubuntu 16.04 und Ubuntu 19.04 verwendet werden, wobei zwischen 42und ein Leerzeichen steht dBm. Daher wird der cutBefehl angewiesen, die Felder 4 und 5 zu drucken. In Ihrer Frage ist kein Platz vorhanden, daher bin ich mir nicht sicher, welche Version Sie verwenden.

Sie könnten auch verwenden:

$ echo $string | cut -d'=' -f3
-42 dBm
  • In diesem Fall cutwird angewiesen, =als Feldtrennzeichen zu verwenden.

Wenn Sie ${string...}jedoch die richtige Syntax verwenden möchten, lautet:

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

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

Beide Methoden funktionieren, um die Teilzeichenfolge nach der letzten zu übernehmen =. Die ursprüngliche Methode 5in Ihrer Frage verstehe ich nicht, wie es funktionieren kann.

WinEunuuchs2Unix
quelle