La variable n'analyse pas en tant que chaîne


10

Problème

J'ai essayé d'extraire le niveau du signal pour le wifi de la manière suivante, dans un script bash (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'essaye d'obtenir une sous-chaîne echo ${string:5}, elle renvoie la même chose.


Débogage:

Si je colle la sortie de wconfig wlan0 | grep -I Signaldirectement 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 Internet, toutes les variables bash sont stockées sous forme de chaînes de caractères. Par conséquent, le résultat du débogage aurait dû être le même que mon problème d'origine. Y a-t-il une raison pour laquelle il n'est pas analysé en tant que texte dans le problème d'origine?

Réponses:


15

En effet, echo $stringn'imprime pas simplement la valeur de string; il effectue d'abord une opération split + glob - dont l'une des conséquences est que les espaces blancs principaux sont élidés:

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

tandis 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'espaces au début de $string- en fait, il y en a plus de 5, donc la suppression de 5 laisse toujours une chaîne avec des espaces en tête, ce qu'une élimination de sous-chaîne ( ${string:5}) sans guillemets é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 supplémentaire, voir:


4
Tl; dr toujours citer vos variables
gronostaj

6

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 wlp60s0par wlan0.
  • Notez que cela utilise Ubuntu 16.04 et Ubuntu 19.04 où il y a un espace entre 42et dBm. En tant que telle, la cutcommande est invitée à imprimer les champs # 4 et # 5. Dans votre question, il n'y a pas d'espace donc je ne sais pas quelle version vous utilisez.

Vous pouvez également utiliser:

$ echo $string | cut -d'=' -f3
-42 dBm
  • Dans ce cas, il cutest dit d'utiliser =comme délimiteur de champ.

Si vous souhaitez utiliser ${string...}la syntaxe correcte:

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

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

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.