Mejor manera de ejecutar un solo bucle for en lugar de dos bucles for

Mejor manera de ejecutar un solo bucle for en lugar de dos bucles for

Esto funciona, pero la forma en que lo hice es un poco tonta. ¿Hay una mejor manera de hacer esto?

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

Así es como se ve ipcs cuando lo ejecuto.

$ 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

Necesito ejecutar estos dos comandos con regularidad.

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

Entonces estaba pensando que podría hacer algo como esto.

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

Quiero hacer ese primer comportamiento hasta que $2 sea igual a Semaphore.

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

Entonces, para resumir, quiero que se ejecute el primer bloque if después de ver "Compartido". Luego quiero el segundo bloque if después de ver "Semáforo".

Respuesta1

Si entiendo correctamente, desea ejecutar el comando ipcrm shm <ids>para todos los segmentos de memoria compartida del usuario bob. Luego, el comando ipcrm -s <ids>para todos los Semaphore Arrays del usuario bob.

Para lograrlo, utilice los siguientes comandos (no es necesario realizar un bucle en un script):

Para la parte de Segmentos de memoria compartida:

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

Para la parte de la matriz de semáforos:

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

Explicación:

Desde la ipcspágina de manual:

   -m     shared memory segments
   -s     semaphore arrays

La awkpieza imprime los identificadores solo cuando el tercer campo es bob.

Respuesta2

Tal vez...

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

Eso elimina líneas que no contienen la cadena.Betocomo el tercer campo delimitado por espaciosoque no tienen en su segundo campoMensajes/Semáforos.

Inserta la cadena ipcrm $1 <field 2>para aquellas líneas que quedan. Cierra la entrada al hacer coincidirMensajesy reemplaza unSemáforoscoincidir con shift.

sedLa salida de es interpretada por un proceso de shell con dos posicionales.shm/-s. Entonces, cuando seddice shiftque Shell deja de ejecutar el comando ipcrm shm <field2>y comienza a ejecutarse -sen lugar de shms.

Supongo que si quisieras una solución de shell pura, esto se aproxima:

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

Respuesta3

Como sugirió slm entu otra pregunta, sugiero hacer esto con un whilebucle en lugar de un forbucle:

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

Esto lee el resultado del ipcscomando una línea a la vez, dividiendo los primeros tres campos como  key, idy owner. Como dice el comentario, usamos la looking_atvariable para realizar un seguimiento de en qué sección estamos. Luego, en cada línea que contiene bobel tercer campo, usamos looking_atpara determinar qué ipcrmopción usar.

información relacionada