Melhor maneira de executar single for loop em vez de dois loops for

4

Isso funciona, mas a maneira como fiz isso é meio boba. Existe uma maneira melhor de fazer isso?

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

    echo $e outside for loop
for e in $(ipcs | awk '{print $2}'); do
    [[ "$e" = "Message" ]] && break
    echo $e
    ipcrm -s $e
done

echo
exit 0

Isto é o que o ipcs parece para mim quando eu o executo.

$ ipcs

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 262145     bob        600        393216     2          dest         
0x00000000 2523138    bob        600        393216     2          dest         
0x00000000 2555907    bob        600        393216     2          dest         
0x00000000 3375108    bob        600        998400     2          dest         
0x00000000 3440645    bob        666        40         1                       

------ Semaphore Arrays --------
key        semid      owner      perms      nsems     
0x000005b1 262146     bob        600        6         

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

Eu preciso executar esses dois comandos regularmente.

ipcrm -s $(ipcs | grep bob | awk '{printf "%s ",$2}')
ipcrm  shm $(ipcs | grep bob | awk '{printf "%s ",$2}')

Então eu estava pensando que poderia fazer algo assim.

if [ '$(ipcs | grep Shared | awk '{print $2}')' == "Shared"]
ipcrm  shm $(ipcs | grep bob | awk '{printf "%s ",$2}')

Eu quero fazer esse primeiro comportamento até que $ 2 seja igual a Semaphore.

if [ '$(ipcs | grep Semaphore | awk '{print $2}')' == "Semaphore"]
ipcrm -s $(ipcs | grep bob | awk '{printf "%s ",$2}'

Então, para resumir, quero que o primeiro bloco seja executado depois que eu vir "Compartilhado". Então eu quero o segundo se bloco depois de ver "Semaphore".

    
por cokedude 10.10.2014 / 10:16

3 respostas

6

Se eu entendi corretamente, você quer executar o comando ipcrm shm <ids> para todos os segmentos de memória compartilhada do usuário bob. Então o comando ipcrm -s <ids> para todos os Arrays Semaphore do usuário bob.

Para conseguir isso, use os seguintes comandos (você não precisa fazer loop em um script):

Para a parte Segmentos de memória compartilhada:

ipcrm shm $(ipcs -m | awk '$3=="bob" {printf "%s ",$2}')

Para a parte da Semaphore Array:

ipcrm -s $(ipcs -s | awk '$3=="bob" {printf "%s ",$2}')

Explicação:

Na% man_de% manpage:

   -m     shared memory segments
   -s     semaphore arrays

A parte ipcs imprime os IDs somente quando o terceiro campo é bob.

    
por 10.10.2014 / 10:32
2

Talvez ...

ipcs | sed -n '
    s/[^ ]*  *//
    /^Messages/q
    /^Semaphores/cshift
    /  *bob .*/!d;s///
    / /!s/./ipcrm $1 &/p
'| sh -s -- shm \-s

Isso exclui as linhas que não contêm a string bob como o terceiro campo delimitado por espaço ou que não tem em seu segundo campo Messages / Semaphores.

Insere a string ipcrm $1 <field 2> para as linhas que permanecem. Ele sai da entrada ao corresponder Mensagens e substitui a correspondência Semáforos com shift .

A saída de

sed é interpretada por um processo shell com dois posicionamentos shm / -s . Então, quando sed diz shift que o shell pára de executar o comando ipcrm shm <field2> e começa a executar -s no shms place.

Acho que se você quiser uma solução de shell puro, isso chega perto:

set -f; IFS='
'; for l in $(ipcs); 
do IFS=\ ;set -- $l
case "$1:$2:${3#bob}" in
(-*:Sh*) a=shm;; 
(-*:Se*) a=-s;; 
(-*:Me*) break 2;;
(*:*:) ipcrm "$a" "$2";;
esac; done
    
por 10.10.2014 / 15:48
-1

Como slm sugeriu em sua outra pergunta , Sugiro fazer isso com um loop while em vez de um loop for :

looking_at=
ipcs | while read key id owner other
do
      # Keep track of which section we’re in.
      if [ "$id" = "Shared" ]               # $id is the second field; i.e., $2.
      then
            looking_at=shm
      elif [ "$id" = "Semaphore" ]
      then
            looking_at=sem
      elif [ "$id" = "Message" ]
      then
            break
      fi
      if [ "$owner" = "bob" ]
      then
            if [ "$looking_at" = "shm" ]
            then
                  ipcrm shm "$id"
            elif [ "$looking_at" = "sem" ]
            then
                  ipcrm -s "$id"
            fi
      fi
done

Isso lê a saída do comando ipcs uma linha por vez, quebrando os três primeiros campos como key , id e owner . Como o comentário diz Usamos a variável looking_at para acompanhar em qual seção estamos. Em seguida, em todas as linhas que contiverem bob no terceiro campo, usamos looking_at para determinar qual ipcrm opção usar.

    
por 10.10.2014 / 20:29