10 votes

La variable n'est pas analysée comme une chaîne de caractères

Problème

J'ai essayé d'extraire le niveau du signal pour le wifi de la manière suivante, dans un bash script (les guillemets semblent ne faire aucune différence) :

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

Si je echo $string J'obtiens ce que j'attends :

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

Mais si j'essaie d'obtenir une sous-chaîne, echo ${string:5} il renvoie la même chose.


Débogage :

Si je colle la sortie de wconfig wlan0 | grep -I Signal directement dans la variable : string="Link Quality=63/70 Signal level=-47dBm" alors tout fonctionne comme prévu.

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

Question : Selon l'internet, toutes les variables bash sont stockées comme des chaînes de caractères. Ainsi, le résultat du débogage aurait dû être le même que celui de mon problème initial. Y a-t-il une raison pour laquelle il n'est pas analysé comme du texte dans le problème original ?

15voto

steeldriver Points 118154

Cela s'explique par le fait que echo $string ne se contente pas d'imprimer la valeur de string ; il effectue d'abord un split+glob dont l'une des conséquences est que les espaces blancs de tête sont élidés :

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

alors que

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

Nous pouvons voir qu'il y a une séquence de caractères d'espacement au début de $string - en fait, il y en a plus de 5, donc en enlevant 5, il reste une chaîne avec des espaces en tête, qu'une expansion de sous-chaîne non citée ( ${string:5} ) élide également :

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

Pour une discussion plus approfondie, voir :

6voto

WinEunuuchs2Unix Points 91128

Cela fonctionne sur ma machine :

$ 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
  • Pour votre machine, remplacez wlp60s0 con wlan0 .
  • Note Ceci est en utilisant Ubuntu 16.04 et Ubuntu 19.04 où il y a un espace entre 42 y dBm . En tant que tel, le cut est chargée d'imprimer les champs n°4 et n°5. Dans votre question, il n'y a pas d'espace, donc je ne suis pas sûr de la version que vous utilisez.

Vous pourriez aussi utiliser :

$ echo $string | cut -d'=' -f3
-42 dBm
  • Dans ce cas cut est prié d'utiliser = comme délimiteur de champ.

Si vous voulez utiliser ${string...} bien que la syntaxe correcte soit :

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

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

L'une ou l'autre méthode fonctionnera pour prendre la sous-chaîne après le dernier = . La méthode originale de 5 dans votre question, je ne comprends pas comment cela peut fonctionner.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X