Bessere Möglichkeit, eine einzelne For-Schleife anstelle von zwei For-Schleifen auszuführen

Bessere Möglichkeit, eine einzelne For-Schleife anstelle von zwei For-Schleifen auszuführen

Das funktioniert, aber die Art, wie ich es gemacht habe, ist irgendwie albern. Gibt es eine bessere Möglichkeit, das zu tun?

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

So sieht ipcs für mich aus, wenn ich es ausführe.

$ 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

Ich muss diese beiden Befehle regelmäßig ausführen.

ipcrm -s $(ipcs | grep bob | awk '{printf "%s ",$2}')
ipcrm  shm $(ipcs | grep bob | awk '{printf "%s ",$2}')

Also dachte ich, ich könnte so etwas machen.

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

Ich möchte dieses erste Verhalten ausführen, bis 2 $ gleich Semaphore sind.

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

Zusammenfassend möchte ich, dass der erste if-Block ausgeführt wird, nachdem ich „Shared“ sehe. Dann möchte ich den zweiten if-Block ausführen, nachdem ich „Semaphore“ sehe.

Antwort1

Wenn ich das richtig verstehe, möchten Sie den Befehl ipcrm shm <ids>für alle Shared Memory Segments des Benutzers Bob ausführen. Dann den Befehl ipcrm -s <ids>für alle Semaphore Arrays des Benutzers Bob.

Verwenden Sie dazu die folgenden Befehle (Sie müssen kein Skript in einer Schleife ausführen):

Für den Teil „Gemeinsam genutzte Speichersegmente“:

ipcrm shm $(ipcs -m | awk '$3=="bob" {printf "%s ",$2}')

Für den Semaphore-Array-Teil:

ipcrm -s $(ipcs -s | awk '$3=="bob" {printf "%s ",$2}')

Erläuterung:

Aus der ipcsManpage:

   -m     shared memory segments
   -s     semaphore arrays

Das awkTeil druckt die IDs nur, wenn das 3. Feld Bob ist.

Antwort2

Vielleicht...

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

Dadurch werden Zeilen gelöscht, die die Zeichenfolge nicht enthaltenBobals drittes durch Leerzeichen getrenntes Feldoderdie in ihrem zweiten Feld nicht habenNachrichten/Semaphoren.

Es fügt den String ipcrm $1 <field 2>für die verbleibenden Zeilen ein. Es beendet die Eingabe, wennMitteilungenund es ersetzt einSemaphorenÜbereinstimmung mit shift.

sedDie Ausgabe wird von einem Shell-Prozess mit zwei Positionsalarmen interpretiert.shm/-s. Wenn dies also der sedFall ist shift, stoppt die Shell die Ausführung des Befehls ipcrm shm <field2>und startet die Ausführung -san der Stelle von shms.

Ich denke, wenn Sie eine reine Shell-Lösung wollten, kommt diese hier dem nahe:

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

Antwort3

Wie slm vorgeschlagen hat aufdeine andere Frage, ich schlage vor, dies mit einer whileSchleife statt einer forSchleife zu tun:

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

Dadurch wird die Ausgabe des ipcsBefehls zeilenweise gelesen, wobei die ersten drei Felder als  key, id, und aufgeteilt werden owner. Wie im Kommentar angegeben, verwenden wir die looking_atVariable, um zu verfolgen, in welchem ​​Abschnitt wir uns befinden. Anschließend bobverwenden wir in jeder Zeile, die im dritten Feld enthält, looking_atum zu bestimmen, welche ipcrmOption verwendet werden soll.

verwandte Informationen