運行單一 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 區塊。然後我想要在看到「信號量」後的第二個 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 時,該awk部件才會列印 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的輸出由具有兩個位置的 shell 進程解釋勻稱/-s。因此,當sed表示shiftshell 停止運行命令ipcrm shm <field2>並開始-s在 shms 位置運行時。

我想如果你想要一個純 shell 解決方案,這很接近:

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這次 讀取一行指令的輸出,將前三個欄位分解為keyidowner。正如註釋所說,我們使用變數來looking_at追蹤我們所在的部分。boblooking_atipcrm

相關內容