Melhor maneira de executar um loop for único em vez de dois loops for

Melhor maneira de executar um loop for único em vez de dois loops for

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

É assim que o ipcs fica para mim quando 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

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}')

Quero fazer esse primeiro comportamento até que $2 seja igual ao Semáforo.

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 if seja executado depois de ver "Compartilhado". Então eu quero o segundo bloco if depois de ver "Semáforo".

Responder1

Se bem entendi, você deseja executar o comando ipcrm shm <ids>para todos os segmentos de memória compartilhada do usuário bob. Em seguida, o comando ipcrm -s <ids>para todos os Semaphore Arrays do usuário bob.

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

Para a parte de segmentos de memória compartilhada:

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

Para a parte do Semaphore Array:

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

Explicação:

Na ipcspágina de manual:

   -m     shared memory segments
   -s     semaphore arrays

A awkparte imprime os ids somente quando o terceiro campo é bob.

Responder2

Talvez...

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

Isso exclui linhas que não contêm a stringprumocomo o terceiro campo delimitado por espaçoouque não possuem em seu segundo campoMensagens/Semáforos.

Ele insere a string ipcrm $1 <field 2>para as linhas que permanecem. Ele encerra a entrada ao combinarMensagense substitui umSemáforoscombinar com shift.

seda saída de é interpretada por um processo shell com duas posicionaisshm/-s. Então, quando seddiz shiftque o shell para de executar o comando ipcrm shm <field2>e começa a executar -sno local shms.

Eu acho que se você quisesse uma solução de shell pura, 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

Responder3

Como slm sugeriu emsua outra pergunta, sugiro fazer isso com um whileloop em vez de um forloop:

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 ipcscomando uma linha por vez, dividindo os três primeiros campos como  key, id, e owner. Como diz o comentário, usamos a looking_atvariável para controlar em qual seção estamos. Então, em cada linha contida bobno terceiro campo, usamos looking_atpara determinar qual ipcrmopção usar.

informação relacionada