ディスプレイテーブルの整列方法

ディスプレイテーブルの整列方法

psコマンドとして機能し、表示したい独自のプロパティを使用するスクリプトを作成しようとしています。 psコマンドでは、プロセスが次のようになるとします。

sas 24431     1  0 Oct10 ?        00:51:08 /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs

私はこれを次のように表示したいと思います。

UID  PID    APPNAME
sas  24431  -Dapp.name=myApp
sas  24432  -Dapp.name=myApp2
sas  24433  -Dapp.name=myApp3

メモ:このapp.name属性は、psコマンドから抽出されたコマンドパラメータです。

これは私のスクリプトです。

echo -e "PID\tUSERID\t\tAPPNAME"
ps -u $USER -f |grep "java"|grep -v "grep"|
while read LINE 
do 
  #Get pid from the line
  PID=$(cut -d" " -f2 <<< $LINE);
  #Get parameter value called "-Dapp.name or -DprojectName" 
  #from the ps command for the process
  APPNAME=$(ps -f $PID | awk 'BEGIN {RS=" "}; /-Dapp.name|-DprojectName/');
  USERID=$(cut -d" " -f1 <<< $LINE);

 echo -e $PID"\t"$USERID"\t"$APPNAME;
done;

今私が望む方法で動作します。しかし、時々ソートがめちゃくちゃになることもあります。また、このスクリプトを1行のコマンドで最適化できますか?

どんな助けでも大変感謝します。

答え1

一般的なテーブルソートにはこのcolumnユーティリティが必要です。

たとえば、

(
 printf 'PID\tUSER\tAPPNAME\n'
 printf '%s\t%s\t%s\n' "1" "john" "foo bar"
 printf '%s\t%s\t%s\n' "12345678" "someone_with_a_long_name" "pop tart"
) | column -t -s $'\t'

結果:

PID       USER                      APPNAME
1         john                      foo bar
12345678  someone_with_a_long_name  pop tart

答え2

また、このスクリプトを1行のコマンドで最適化できますか?

-o可能であれば、コマンドオプションを使用して目的のフィールドのみを出力psし、java必要なプロセスと特定のコマンドパラメータと一致するように後処理を検討します。

ps -u $USER -o uname=,pid=,args= | 
  gawk -vOFS='\t' '/java/ {print $1,$2,substr($0,match($0,"-D(app[.]name)|(projectName)[^[:space:]]*"),RLENGTH)}'

それともこんなことかもしれませんperl免責事項:Perlに関する私の知識はおおよそのものです。)

ps -u $USER -o uname=,pid=,args= | 
  perl -anle 'print join "\t", @F[0], @F[1], grep /-D(app[.]name)|(projectName)/,@F if /java/'

答え3

次の出力形式を使用する別のものがありますps

#!/usr/bin/sh -f
printf '%-8.7s%-8s%s\n' $(
     ps -o uname=UID,pid=PID,args=APPNAME | 
     sed -n '1p;s/\( [0-9]* \).*\(-Dapp.name=[^ ]*\).*/\1\2/p'
)

フォーマット文字列に応じて、3つの引数がすべてprintf印刷されます。

  1. 右側の最初のスペースは標準のタブ幅である8文字で埋められ、最大7文字に切り捨てられます。
  2. 右から2番目のスペースは、標準のタブ幅である8文字で埋められます。
  3. 3番目の後ろには\nelineが続きます。

コマンドの置き換えはいいえリーダー故意に。バンラインで-f次の点に注意してくださいsh。これは、シェルが次のことを行う必要があることを指定します。いいえglob - シェル特殊文字に基づいてファイル名をランダムに生成するリスクはありません。コマンド置換は、デフォルトで$IFSスペース、タブ、改行などに分割されます。

コマンド置換でps3つの列を印刷します - タイトルユーザーIDPIDアプリケーション名psPOSIXで指定いいえすべてのフィールドのスペースを印刷します。を除いてフィールドargs=。したがって、最初の2列は$IFS安全です。ただし、文字列をフィールド-Dapp.nameから取得するには処理する必要があります。args=

だからsedフィルタリングしてください。複数のスペースと文字列を含む行に-Dapp.name=次のように印刷されます。

  1. 最初に一連の空白、その後には0個以上の数字、その後には空白とその前のすべての数字...
  2. 文字列を含むシーケンスの最後の発生-Dapp.name=次に、空白が発生する前のすべての文字が続きます。

sed交換は列ヘッダーには影響しません1p-Dapp.name=ひも。他のすべての行は出力から削除されます。

printfsed出力分割を適用した後、$IFS出力は次のようになると予想できます。

UID     PID     APPNAME
sas     24431   -Dapp.name=myApp
sas     24431   -Dapp.name=myApp
sas     24431   -Dapp.name=myApp
sas     24431   -Dapp.name=myApp
sas     24431   -Dapp.name=myApp

しかし、私の考えでは、次のsedステートメントが優れています。

sed -n '1p;s/\( [0-9]* \).*-Dapp.name=\([^ ]*\).*/\1\2/p'

基本的には同じですが、除くと-Dapp.name=部分\2なので、次のように印刷されます...

UID     PID     APPNAME
sas     24431   myApp
sas     24431   myApp
sas     24431   myApp

なぜなら、そうだからただ以下を含む行を印刷します。-Dapp.name=とにかく、それを含む順序は当然と考えられる混乱だけです。

関連情報