二重引用符を使用するだけでこれを実行できることがわかりました:
while read -r proc; do
#do work
done <<< "$(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)"
これにより、各項目ではなく各行が配列に保存されます。
決して for
内部フィールド セパレータの値を変更しない限り、シェル コマンドの結果を 1 行ずつ処理する場合はループします。 $IFS
\n
まで .これは、行が単語分割の対象になるためです。 これが実際の結果につながります。たとえば、次のようなファイルがあるとします:
foo bar
hello world
以下 for ループ
for i in $(cat file); do
echo "$i"
done
あなたに与えます:
foo
bar
hello
world
IFS='\n'
を使用しても 行はまだ ファイル名展開 の対象になる可能性があります
while
を使用することをお勧めします + read
代わりに read
のため 行ごとに読み取ります。
さらに、 pgrep
を使用します 特定のバイナリに属する pid を検索している場合。ただし、python は python2.7
のように異なるバイナリとして表示される場合があるため、 または python3.4
-f
を渡すことをお勧めします pgrep
まで python
というバイナリを検索するだけでなく、コマンド ライン全体を検索します。 .しかし、これは cat foo.py
のように開始されたプロセスも見つけます .あなたは警告されました!最後に、pgrep
に渡された正規表現を改良できます。
例:
pgrep -f python | while read -r pid ; do
echo "$pid"
done
または、プロセス名も必要な場合:
pgrep -af python | while read -r line ; do
echo "$line"
done
プロセス名と pid を別々の変数に入れたい場合:
pgrep -af python | while read -r pid cmd ; do
echo "pid: $pid, cmd: $cmd"
done
ほら、read
コマンドの出力を 1 行ずつ処理する柔軟で安定した方法を提供します。
ところで、あなたが ps .. | grep
を好むなら pgrep
以上のコマンドライン 次のループを使用してください:
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
etime
の順序をどのように変更したかに注意してください と cmd
.したがって、cmd
を読み取ることができます 、空白を含めることができ、単一の変数に。 read
のため、これは機能します 変数を指定した回数だけ、行を変数に分解します。行の残りの部分 (おそらく空白を含む) は、コマンド ラインで指定された最後の変数に割り当てられます。
for
を使用する場合 bash でループすると、デフォルトで指定されたリストが whitespaces
で分割されます 、これは、いわゆる Internal Field Seperator を使用して適応させることができます 、または IFS
IFS 展開後の単語分割、および read 組み込みコマンドで行を単語に分割するために使用される内部フィールド区切り文字。デフォルト値は "" です。
あなたの例では、 IFS
を伝える必要があります new-lines
を使用するには ブレークポイントとして。
IFS=$'\n'
for tbl in $(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh)
do
echo $tbl
done
この例は、私のマシンで次の出力を返します。
668 /usr/bin/python /usr/bin/ud 03:05:54
27892 python 00:01