La variable no se analiza como una cadena

10

Problema

Traté de extraer el nivel de señal para wifi de la siguiente manera, en un script bash (las citas parecen no hacer ninguna diferencia):

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

Si yo echo $string, obtengo lo que espero:

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

Pero si trato de obtener una subcadena, echo ${string:5}devuelve lo mismo.


Depuración:

Si pego el resultado de wconfig wlan0 | grep -I Signaldirectamente en la variable: string="Link Quality=63/70 Signal level=-47dBm"entonces todo funciona como se esperaba.

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

Pregunta: Según Internet, todas las variables bash se almacenan como cadenas de caracteres. Por lo tanto, el resultado de la depuración debería haber sido el mismo que mi problema original. ¿Hay alguna razón por la que no se analiza como texto en el problema original?

Ion Sme
fuente

Respuestas:

15

Esto se debe a echo $stringque no simplemente imprime el valor de string; primero realiza una operación split + glob , una de cuyas consecuencias es que se elimina el espacio en blanco principal:

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

mientras

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

Podemos ver que hay una secuencia de caracteres de espacios en blanco al comienzo de $string- de hecho, hay más de 5, por lo que eliminar 5 todavía deja una cadena con espacios en blanco ${string:5}iniciales , que una expansión de subcadena sin comillas ( ) también elimina:

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

Para una discusión adicional ver:

conductor de acero
fuente
44
Tl; dr siempre cita tus variables
gronostaj
6

Esto funciona en mi máquina:

$ 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
  • Para su máquina reemplace wlp60s0con wlan0.
  • Tenga en cuenta que esto está usando Ubuntu 16.04 y Ubuntu 19.04 donde hay un espacio entre 42y dBm. Como tal, el cutcomando tiene instrucciones de imprimir los campos # 4 y # 5. En su pregunta no hay espacio, así que no estoy seguro de qué versión está utilizando.

También puedes usar:

$ echo $string | cut -d'=' -f3
-42 dBm
  • En este caso cutse le dice que lo use =como delimitador de campo.

Si desea usar, ${string...}aunque la sintaxis correcta es:

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

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

Cualquiera de los métodos funcionará para tomar la subcadena después de la última =. El método original de 5en su pregunta no entiendo cómo puede funcionar.

WinEunuuchs2Unix
fuente