두 개의 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 블록이 실행되기를 원합니다. 그런 다음 "Semaphore"를 본 후 두 번째 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

awk부분은 세 번째 필드가 bob인 경우에만 ID를 인쇄합니다.

답변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의 출력은 두 개의 위치가 있는 쉘 프로세스에 의해 해석됩니다.shm/-s. 따라서 쉘이 명령 실행을 중지 하고 shms 위치에서 실행을 시작한다고 sed말하면 .shiftipcrm shm <field2>-s

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

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

관련 정보