2 つの for ループではなく 1 つの for ループを実行するより良い方法

2 つの for ループではなく 1 つの 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

これら 2 つのコマンドを定期的に実行する必要があります。

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」を確認した後に実行する必要があります。次に、2 番目の 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部分は、3 番目のフィールドが bob の場合にのみ ID を出力します。

答え2

多分...

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

文字列を含まない行を削除しますボブ3番目のスペースで区切られたフィールドとしてまたは2番目のフィールドにないメッセージ/セマフォ。

ipcrm $1 <field 2>残りの行に文字列を挿入します。一致したら入力を終了します。メッセージそしてそれはセマフォと一致shift

sedの出力は、2つの位置を持つシェルプロセスによって解釈されますshm/-sつまり、はシェルがコマンドの実行を停止し、shm の代わりに実行を開始すること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

これは、コマンドの出力をipcs1 行ずつ読み取り、最初の 3 つのフィールドを keyid、に分割しますowner。コメントにあるように、looking_at変数を使用して、現在どのセクションにいるかを追跡します。次に、bob3 番目のフィールドに が含まれるすべての行で、 を使用して、使用するオプションlooking_atを決定しますipcrm

関連情報