运行单个 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变量来跟踪我们所在的部分。然后,在bob第三个字段中包含的每一行上,我们使用变量looking_at来确定ipcrm要使用哪个选项。

相关内容