Bash não é igual à comparação de strings

2

Por que isso causa um loop infinito?

#!/bin/bash
while [[ "$(ipcs | awk '{print $2}')" != "Semaphore" ]]; do
  #Gonna get rid of the echo after working
  echo "$(ipcs | awk '{print $2}')"
  #I want to keep this
  ipcrm shm "$(ipcs | awk '{print $2}')"
  #I want this run after breaking out of the loop until I reach the string
  #Message. 
  ipcrm -s "$(ipcs | awk '{print $2}')"
done      
echo
exit 0

Eu verifiquei que acabei pegando o Semaphore, então ele deve sair do loop while.

$ echo $(ipcs | awk '{print $2}')
Shared shmid 262145 294914 2326531 Semaphore semid Message msqid


$ ipcs

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 262145     bob        600        393216     2          dest         
0x00000000 294914     bob        600        393216     2          dest         
0x00000000 2490371    bob        600        998400     2          dest         

------ Semaphore Arrays --------
key        semid      owner      perms      nsems     

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    

$ echo $(ipcs |  awk '{print $1}')
------ key 0x00000000 0x00000000 0x00000000 ------ key ------ key

$ echo $(ipcs |  awk '{print $2}')
Shared shmid 262145 294914 2490371 Semaphore semid Message msqid
    
por cokedude 09.10.2014 / 15:45

2 respostas

4

$(ipcs | awk '{print $2}') nunca é igual a Semaphore . É sempre igual a:

Shared shmid 262145 294914 2326531 Semaphore semid Message msqid

Você provavelmente quer algo como:

for e in $(ipcs | awk '{print $2}'); do
    [[ "$e" = "Semaphore" ]] && break
    echo $e
done

echo
exit 0

Você também pode gostar deste awk solution:

ipcs | awk '$2 == "Semaphore" {exit;} $2 != "" {print $2}'

Uma pequena explicação:

  • Se o segundo campo for Semáforo , saia.
  • Caso contrário, se este campo não estiver vazio, imprima-o.

Aqui estão algumas soluções alternativas (supondo que eu entendi suas necessidades aqui):

# List all shared memory segments keys
ipcs -m | awk 'NR > 3 && $1 != "" {print $1}'

# List all shared memory segments IDs
ipcs -m | awk 'NR > 3 && $2 != "" {print $2}'

Para cada um desses exemplos, você pode repetir o resultado:

for e in $(above command); do
    echo $e
done
    
por 09.10.2014 / 15:53
1

Aqui está uma maneira ligeiramente diferente de abordar seu loop while:

$ while read line; do 
    echo "$line"; 
    if [[ "$line" != *Semaphore* ]]; then 
        echo "not semaphore"; 
    else 
        echo "is semaphore"; 
    fi;
  done < <(ipcs | awk '{print $2}')

Que produz esta saída:

...
not semaphore
814972976
not semaphore
815005745
not semaphore
817070167
not semaphore

not semaphore
Semaphore
is semaphore
semid
not semaphore

Observe quando ele chega na string "Semaphore" que ele identifica corretamente.

    
por 09.10.2014 / 16:25