디스플레이 테이블을 잘 정렬하는 방법

디스플레이 테이블을 잘 정렬하는 방법

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

일반적인 테이블 정렬에는 이 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

또한 이 스크립트를 한 줄 명령으로 최적화할 수 있습니까?

-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. 오른쪽에서 두 번째 공백은 표준 탭 너비인 8자로 채워집니다.
  3. 세 번째 뒤에는 \neline이 옵니다.

명령 대체는아니요선두고의로. Bang-line에서 -f다음 사항에 유의하십시오 sh. 이는 쉘이 다음을 수행해야 함을 지정합니다.아니요glob - 쉘 특수 문자를 기반으로 파일 이름을 무작위로 생성할 위험이 없습니다. 명령 대체는 $IFS기본적으로 공백, 탭, 줄 바꿈 등으로 분할됩니다.

명령 대체에서 ps3개의 열을 인쇄합니다 - 제목사용자 ID,PID, 그리고애플리케이션 이름. psPOSIX에 의해 지정됩니다아니요모든 필드의 공백을 인쇄하세요.제외하고필드 args=. 따라서 처음 두 열은 $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=어쨌든, 그것을 포함한 순서는 당연하게 여겨질 수 있는 혼란일 뿐입니다.

관련 정보