Лучший способ запустить один цикл for вместо двух циклов for

Лучший способ запустить один цикл for вместо двух циклов for

Это работает, но то, как я это сделал, немного глупо. Есть ли способ сделать это лучше?

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

Вот как выглядит ipcs для меня, когда я его запускаю.

$ 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

Мне нужно регулярно выполнять эти две команды.

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

Поэтому я подумал, что могу сделать что-то подобное.

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

Я хочу выполнять это первое поведение до тех пор, пока $2 не станет равным Semaphore.

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

Итак, подведем итог: я хочу, чтобы первый блок if запускался после того, как я увижу «Shared». Затем я хочу, чтобы второй блок if запускался после того, как я увижу «Semaphore».

решение1

Если я правильно понял, вы хотите запустить команду ipcrm shm <ids>для всех сегментов общей памяти пользователя bob. Затем команду ipcrm -s <ids>для всех массивов семафоров пользователя bob.

Для этого используйте следующие команды (вам не нужно зацикливать скрипт):

Для раздела «Сегменты общей памяти»:

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

Для части массива семафоров:

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

Объяснение:

Из ipcsстраницы руководства:

   -m     shared memory segments
   -s     semaphore arrays

Часть awkпечатает идентификаторы только тогда, когда третье поле — bob.

решение2

Может быть...

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

Это удаляет строки, которые не содержат строкубобкак третье поле, разделенное пробеломиликоторые не имеют во втором полеСообщения/Семафоры.

Вставляет строку ipcrm $1 <field 2>для тех строк, которые остались. Он прекращает ввод при сопоставленииСообщенияи он заменяетСемафорысоответствует shift.

sedвывод интерпретируется процессом оболочки с двумя позиционнымишм/-с. Итак, когда sedговорится shift, что оболочка прекращает выполнение команды ipcrm shm <field2>и начинает работать -sвместо shms.

Думаю, если вам нужно чисто оболочное решение, то это будет близко:

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

решение3

Как slm предложил наВаш другой вопрос, я предлагаю сделать это с помощью whileцикла, а не 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

Это считывает вывод команды ipcsпо одной строке за раз, разбивая первые три поля на  key, id, и owner. Как говорится в комментарии, мы используем looking_atпеременную для отслеживания раздела, в котором мы находимся. Затем, в каждой строке, содержащей bobтретье поле, мы используем , looking_atчтобы определить, какую ipcrmопцию использовать.

Связанный контент