두 개의 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가 세마포어와 같아질 때까지 첫 번째 작업을 수행하고 싶습니다.

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

요약하자면, "shared"를 본 후 첫 번째 if 블록이 실행되기를 원합니다. 그런 다음 "세마포어"를 본 후 두 번째 if 블록을 원합니다.

답변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

위젯은 세 번째 필드가 bob 인 경우에만 awkID를 인쇄합니다 .

답변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의 출력은 두 위치의 쉘 프로세스에 의해 해석됩니다.매끈한/-s. 따라서 sedshift이 명령 실행을 중지 ipcrm shm <field2>하고 -sshms 위치에서 실행을 시작합니다.

순수한 쉘 솔루션을 원한다면 다음과 같습니다.

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

관련 정보