Nie for
Schleife über die Ergebnisse einer Shell-Befehl möchten, wenn Sie es Zeile für Zeile verarbeiten, es sei denn Sie werden den Wert des internen Feldtrenn$IFS
-\n
ändern. Dies liegt daran, dass die Zeilen das Thema Wortspaltung bekommen, was zu den tatsächlichen Ergebnissen führt, die Sie sehen. Bedeutung, wenn Sie zum Beispiel eine Datei wie folgt aussehen:
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'
die Linien verwenden könnten noch unter dem Vorbehalt erhalten von Filename expansion
Ich empfehle stattdessen while
+ read
zu verwenden, weil read
zeilenweise liest.
Darüber hinaus würde ich pgrep
verwenden, wenn Sie nach PIDS suchen, die zu einer bestimmten Binärdatei gehören. Da Python jedoch als verschiedene Binärdateien angezeigt werden kann, wie python2.7
oder python3.4
, empfehle ich, -f
an pgrep
zu übergeben, wodurch die gesamte Befehlszeile gesucht wird und nicht nur nach Binärdateien mit der Bezeichnung python
gesucht wird. Es werden aber auch Prozesse gefunden, die wie cat foo.py
gestartet wurden. Du wurdest gewarnt! Am Ende können Sie die Regex verfeinern, die wie gewünscht an pgrep
übergeben wird.
Beispiel:
pgrep -f python | while read -r pid ; do
echo "$pid"
done
oder wenn Sie wollen auch den Prozessname:
pgrep -af python | while read -r line ; do
echo "$line"
done
Wenn Sie den Prozessnamen möchten und die pid in separaten Variablen:
pgrep -af python | while read -r pid cmd ; do
echo "pid: $pid, cmd: $cmd"
done
Sie siehe read
bietet eine flexible und stabile Möglichkeit, die Ausgabe eines Befehls Zeile für Zeile zu verarbeiten.
Btw, wenn Sie Ihre ps .. | grep
Befehlszeile über pgrep
verwenden Sie die folgende Schleife bevorzugen:
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 der etime
und cmd
geändert. So kann cmd
, die Whitespace enthalten kann, in eine einzige Variable gelesen werden. Das funktioniert, weil read
die Zeile in Variablen aufteilt, so oft Sie Variablen angegeben haben. Der verbleibende Teil der Zeile - möglicherweise einschließlich Leerzeichen - wird der letzten Variablen zugewiesen, die in der Befehlszeile angegeben wurde.
Ich nehme an, du meintest 'pgrep' nicht 'prep'? – adic26
Oh, sicher ....... Btw, wenn Sie die Zeit benötigen, verwenden Sie "ps -p" $ pid "-o etime" in der Schleife. Natürlich können Sie auch Ihre 'ps .. | grep 'command line, aber pipe immer noch zu' while read ... '... – hek2mgl
Selbst wenn Sie' IFS' setzen, unterliegt die Erweiterung der Befehlsersetzung immer noch der Pfadnamenerweiterung, also ist die 'for' Schleife einfach einfach falsch. – chepner