GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie kann ich die Ausgabe eines Shell-Befehls durchlaufen?

Ich habe festgestellt, dass Sie dies tun können, indem Sie einfach doppelte Anführungszeichen verwenden:

while read -r proc; do
     #do work
done <<< "$(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)"

Dadurch wird jede Zeile im Array gespeichert und nicht jedes Element.


Niemals for Schleifen Sie die Ergebnisse eines Shell-Befehls, wenn Sie ihn Zeile für Zeile verarbeiten möchten, es sei denn, Sie ändern den Wert des internen Feldtrennzeichens $IFS bis \n . Dies liegt daran, dass die Zeilen Gegenstand der Wortaufteilung werden was zu den tatsächlichen Ergebnissen führt, die Sie sehen. Das heißt, wenn Sie zum Beispiel eine Datei wie diese haben:

foo bar
hello world

Die folgende for-Schleife

for i in $(cat file); do
    echo "$i"
done

gibt Ihnen:

foo
bar
hello
world

Auch wenn Sie IFS='\n' verwenden die Zeilen werden möglicherweise immer noch Gegenstand der Dateinamenerweiterung

Ich empfehle die Verwendung von while + read stattdessen weil read liest Zeile für Zeile.

Außerdem würde ich pgrep verwenden wenn Sie nach Pids suchen, die zu einer bestimmten Binärdatei gehören. Da Python jedoch möglicherweise als unterschiedliche Binärdateien angezeigt wird, wie python2.7 oder python3.4 Ich schlage vor, -f zu übergeben bis pgrep Dadurch wird die gesamte Befehlszeile durchsucht, anstatt nur nach Binärdateien mit dem Namen python zu suchen . Dies findet aber auch Prozesse, die wie cat foo.py gestartet wurden . Du wurdest gewarnt! Am Ende können Sie die an pgrep übergebene Regex verfeinern wie Sie es wünschen.

Beispiel:

pgrep -f python | while read -r pid ; do
    echo "$pid"
done

oder wenn Sie auch den Prozessnamen wollen:

pgrep -af python | while read -r line ; do
    echo "$line"
done

Wenn Sie den Prozessnamen und die PID in separaten Variablen haben möchten:

pgrep -af python | while read -r pid cmd ; do
    echo "pid: $pid, cmd: $cmd"
done

Sehen Sie, read bietet eine flexible und stabile Möglichkeit, die Ausgabe eines Befehls Zeile für Zeile zu verarbeiten.

Übrigens, wenn Sie Ihren ps .. | grep bevorzugen Befehlszeile über pgrep Verwenden Sie die folgende Schleife:

ps -ewo pid,etime,cmd | grep python | grep -v grep | grep -v sh \
  | while read -r pid etime cmd ; do
    echo "$pid $cmd $etime"
done

Beachten Sie, wie ich die Reihenfolge von etime geändert habe und cmd . Also um cmd lesen zu können , die Leerzeichen enthalten kann, in eine einzelne Variable. Das funktioniert, weil read zerlegt die Zeile so oft in Variablen, wie Sie Variablen angegeben haben. Der restliche Teil der Zeile - möglicherweise inklusive Whitespace - wird der letzten Variable zugewiesen, die in der Kommandozeile angegeben wurde.


Bei Verwendung von for Schleifen in Bash teilt es die angegebene Liste standardmäßig durch whitespaces , dies kann durch die Verwendung des sogenannten Internen Feldtrenners angepasst werden , oder IFS kurz .

IFS Das interne Feldtrennzeichen, das zum Aufteilen von Wörtern nach der Erweiterung und zum Aufteilen von Zeilen in Wörter mit dem eingebauten Lesebefehl verwendet wird. Der Standardwert ist "".

Für Ihr Beispiel müssten wir IFS angeben um new-lines zu verwenden als Haltepunkt.

IFS=$'\n'

for tbl in $(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)
do
   echo $tbl
done

Dieses Beispiel gibt die folgende Ausgabe auf meinem Computer zurück.

  668 /usr/bin/python /usr/bin/ud    03:05:54
27892 python                            00:01

Linux
  1. Wie kann man die Zeilen einer Datei durchlaufen?

  2. Wie hebt man ein Wort in der Ausgabe von „Katze“ hervor?

  3. Was ist der Unterschied zwischen dem Abrufen der Befehlsausgabe mit "command" und $(command) in der Shell??

  4. Wie kann man feststellen, ob die Ausgabe eines Befehls oder Shell-Skripts Stdout oder Stderr ist?

  5. Wie kann ich die Ausgabe eines Befehls direkt in meine Zwischenablage kopieren?

So verwenden Sie den Linux-Grep-Befehl

So führen Sie Shell-Befehle über einen HTTP-Server aus

So leiten Sie die Shell-Befehlsausgabe um

Wie weist man die Ausgabe eines Befehls einer Shell-Variablen zu?

Wie kann ich die Ausgabe eines Remote-Befehls in die lokale Zwischenablage kopieren?

Die Ausgabe eines Shell-Befehls nur bei Erfolg ausblenden?