質問

これを行いたい:

  1. コマンドを実行
  2. 出力をキャプチャする
  3. 行を選択
  4. その行の列を選択

例として、 $ PID からコマンド名を取得したいとします(これは単なる例であることに注意してください。プロセスIDからのコマンド名-私の本当の問題は、出力形式を制御できない別のコマンドにあります。

ps を実行すると、次のようになります:


  PID TTY          TIME CMD
11383 pts/1    00:00:00 bash
11771 pts/1    00:00:00 ps

ps | egrep 11383 および取得

11383 pts/1    00:00:00 bash

次のステップ: ps | egrep 11383 | cut -d" " -f 4 。出力は次のとおりです。

<absolutely nothing/>

問題は、 cut が出力を単一のスペースでカットし、 ps が2番目と3番目の列の間にスペースを追加してテーブルの類似性を保つことです< code> cut は空の文字列を選択します。もちろん、 cut を使用して4番目のフィールドではなく7番目のフィールドを選択することもできますが、特に出力が可変で事前に不明な場合はどうすればわかりますか。

役に立ちましたか?

解決

1つの簡単な方法は、 tr 繰り返されるフィールド区切り文字を絞り出すには:

$ ps | egrep 11383 | tr -s ' ' | cut -d ' ' -f 4

他のヒント

最も簡単な方法は awk を使用することだと思います。例:

$ echo "11383 pts/1    00:00:00 bash" | awk '{ print $4; }'
bash

tr -s '' オプションは、先頭のスペースを削除しません。列が右揃えの場合( ps pidなど)...

$ ps h -o pid,user -C ssh,sshd | tr -s " "
 1543 root
19645 root
19731 root

最初の列である場合、これらのフィールドの一部で切り取りを行うと空白行になります:

$ <previous command> | cut -d ' ' -f1

19645
19731

スペースの前に置かない限り、明らかに

$ <command> | sed -e "s/.*/ &/" | tr -s " "

今、(名前ではなく)pid番号のこの特定の場合に、 pgrep と呼ばれる関数があります:

$ pgrep ssh


シェル関数

ただし、一般に read コマンドにはきちんとしたものがあるため、実際には簡潔にシェル関数を使用することも可能です。

$ <command> | while read a b; do echo $a; done

読み取る最初のパラメーター a は最初の列を選択し、さらにある場合はその他すべて b に入れられます。その結果、列の数 +1 以上の変数は必要ありません。

だから、

while read a b c d; do echo $c; done

は3番目の列を出力します。私のコメントに示されているように...

パイプされた読み取りは、呼び出し元のスクリプトに変数を渡さない環境で実行されます。

out=$(ps whatever | { read a b c d; echo $c; })

arr=($(ps whatever | { read a b c d; echo $c $b; }))
echo ${arr[1]}     # will output 'b'`


アレイソリューション

したがって、@ frayserによる答えになります。これは、デフォルトでスペースになっているシェル変数IFSを使用して、文字列を配列に分割することです。ただし、Bashでのみ機能します。 DashとAshはサポートしていません。 Busyboxで文字列をコンポーネントに分割するのは本当に大変でした。単一のコンポーネントを取得して(awkを使用するなど)、必要なパラメーターごとにそれを繰り返すのは簡単です。しかし、同じ行で繰り返しawkを呼び出すか、同じ行でエコー付きの読み取りブロックを繰り返し使用することになります。効率的でもきれいでもありません。そのため、 $ {name %% *} などを使用して分割することになります。慣れている機能の半分以上がなくなっていれば、実際にはシェルスクリプトはあまり楽しくないので、Pythonのスキルに憧れます。しかし、そのようなシステムにはpythonでさえインストールされず、そうではなかったと想定できます;-)。

試用

ps |&
while read -p first second third fourth etc ; do
   if [[ $first == '11383' ]]
   then
       echo got: $fourth
   fi       
done

brianeggeのawkソリューションと同様に、Perlに相当するものを次に示します。

ps | egrep 11383 | perl -lane 'print $F[3]'

-a は自動分割モードを有効にし、 @F 配列に列データを取り込みます。
データがスペース区切りではなくコンマ区切りの場合は、 -F、を使用します。

Perlは1ではなく0からカウントを開始するため、フィールド3が出力されます

正しい行(行番号6の例)の取得は頭と尾で行われ、正しい単語(単語番号4)はawkでキャプチャできます:

command|head -n 6|tail -n 1|awk '{print $4}'

配列変数の使用

set $(ps | egrep "^11383 "); echo $4

または

A=( $(ps | egrep "^11383 ") ) ; echo ${A[3]}

これらのすべての作業を行う代わりに、出力形式を変更するps機能を使用することをお勧めします。

ps -o cmd= -p 12345

pidが指定され、それ以外のプロセスのcmmand行を取得します。

これはPOSIXに準拠しているため、移植性があると見なされる可能性があります。

あなたのコマンド

ps | egrep 11383 | cut -d" " -f 4
回答で説明されているように、

tr -s を使用してスペースを絞り込みます。

ただし、1つのコマンドでこれらのすべてのアクションを処理するため、 awk を使用することもできます。

ps | awk '/11383/ {print $4}'

11383 を含む行の4番目の列を印刷します。これが 11383 と一致するようにしたい場合は、行の先頭に表示される場合、 ps | awk '/ ^ 11383 / {print $ 4}'

Bashの set は、すべての出力を位置パラメーターに解析します。

たとえば、 set $(free -h)コマンドでは、 echo $ 7 は&quot; Mem:&quot;

と表示されます
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top