A variável não analisa como sequência

10

Problema

Tentei extrair o nível de sinal do wifi da seguinte maneira, em um script bash (as aspas parecem não fazer diferença):

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

Se eu echo $stringconseguir o que espero:

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

Mas se eu tentar obter uma substring echo ${string:5}, ela retornará a mesma coisa.


Depuração:

Se eu colar a saída wconfig wlan0 | grep -I Signaldiretamente na variável: string="Link Quality=63/70 Signal level=-47dBm"tudo funcionará conforme o esperado.

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

Pergunta: De acordo com a Internet, todas as variáveis ​​do bash são armazenadas como cadeias de caracteres. Assim, o resultado da depuração deveria ter sido o mesmo que o meu problema original. Existe algum motivo para não ser analisado como texto no problema original?

Ion Sme
fonte

Respostas:

15

Isso ocorre porque echo $stringsimplesmente não imprime o valor de string; primeiro, ele executa uma operação split + glob - uma das conseqüências é que o espaço em branco à esquerda é elidido:

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

enquanto que

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

Podemos ver que há uma sequência de caracteres de espaço em branco no início $string- na verdade, existem mais de 5, portanto, a remoção de 5 ainda deixa uma cadeia de caracteres com espaço em branco à esquerda, que ${string:5}também é excluído por uma expansão de cota ( ) não citada:

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

Para discussões adicionais, consulte:

chave de aço
fonte
4
Tl; dr sempre citar suas variáveis
gronostaj
6

Isso funciona na minha 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 a sua máquina, substitua wlp60s0por wlan0.
  • Observe que isso está usando o Ubuntu 16.04 e o Ubuntu 19.04, onde há um espaço entre 42e dBm. Como tal, o cutcomando é instruído a imprimir os campos 4 e 5. Na sua pergunta, não há espaço, então não tenho certeza de qual versão você está usando.

Você também pode usar:

$ echo $string | cut -d'=' -f3
-42 dBm
  • Nesse caso, cuté dito para usar =como delimitador de campo.

Se você deseja usar, ${string...}a sintaxe correta é:

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

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

Qualquer um dos métodos funcionará para obter a substring após o último =. O método original da 5sua pergunta não entendo como isso pode funcionar.

WinEunuuchs2Unix
fonte