텍스트 파일 데이터 구조에서 일부 텍스트 조작을 수행하고 내용을 약간 변경하는 쉘 스크립트

텍스트 파일 데이터 구조에서 일부 텍스트 조작을 수행하고 내용을 약간 변경하는 쉘 스크립트

텍스트가 너무 많아서 미리 죄송합니다. 기존 데이터 구조를 표현하는 방법을 모르겠습니다.

서버로부터 매 시간 수집된 약 1년 분량의 로그를 받았습니다.

안타깝게도 데이터 수집 스크립트를 수정하여 원하는 방식으로 파일을 빌드하기는 쉽지만 여전히 수천 개의 기존 파일을 변환해야 합니다. 나는 여기서 약간의 어려움을 겪고 있으며 그것이 내 능력 밖의 일인지 아니면 정신적으로 이 길을 필요한 것보다 더 어렵게 만들고 있다고 의심합니다.

다음은 실행 중 하나의 기본 반복입니다(매시간 5분마다 실행).

2350
 id pool                 type rid rset                  min  max size used load
  5 SUNWtmp_serverxd1z1      pset   1 SUNWtmp_serverxd1z1       104  104  104 0.00 6.25
  4 SUNWtmp_serverxd1z2      pset   2 SUNWtmp_serverxd1z2        16   16   16 0.00 0.91
  0 pool_default         pset  -1 pset_default           24  66K   24 0.00 1.74

 id pool                 type rid rset                  min  max size used load
  5 SUNWtmp_serverxd1z1      pset   1 SUNWtmp_serverxd1z1       104  104  104 5.01 6.21
  4 SUNWtmp_serverxd1z2      pset   2 SUNWtmp_serverxd1z2        16   16   16 0.97 0.91
  0 pool_default         pset  -1 pset_default           24  66K   24 3.73 1.78

출력은 잘리지만 이전 타임스탬프부터 다음 타임스탬프까지 50줄이 계속됩니다.

블록 인용에 숫자를 표시하는 방법을 모르지만 각 실행의 길이는 50줄입니다(모두 하루에 약 14400줄의 파일로 결합되며 각 줄 앞의 필드는 다음에서 파생된 날짜입니다. 파일 이름.

이것이 그들이 원하는 방식입니다. 필드 위치는 공백에 관한 한 중요하지 않은 것 같습니다. 2까지 반복되는 것으로 표시되지만 실제로는 50개 행(전체 데이터 수집 실행)마다 반복되는 새 필드 "int"를 포함한 상대 필드 위치입니다. 01부터 시작합니다.

date     hhmm int id pool                type rid rset                  min  max size used load
20121105 2350 01  5 SUNWtmp_serverxd1z1      pset   1 SUNWtmp_serverxd1z1       104  104  104 0.00 6.25
20121105 2350 01  4 SUNWtmp_serverxd1z2      pset   2 SUNWtmp_serverxd1z2        16   16   16 0.00 0.91
20121105 2350 01  0 pool_default         pset  -1 pset_default           24  66K   24 0.00 1.74

date     hhmm int id pool                type rid rset                  min  max size used load
20121105 2350 02  5 SUNWtmp_serverxd1z1      pset   1 SUNWtmp_serverxd1z1       104  104  104 5.01 6.21
20121105 2350 02  4 SUNWtmp_serverxd1z2      pset   2 SUNWtmp_serverxd1z2        16   16   16 0.97 0.91
20121105 2350 02  0 pool_default         pset  -1 pset_default           24  66K   24 3.73 1.78

나는 몇 가지 sed 및 awk oneliner를 시도했지만 슬프게도 1liner가 처리할 수 있는 것보다 더 정교한 방식으로 텍스트를 조작할 수 없었다는 것을 깨달았습니다. 그 시점에서 나는 이 파일에 그보다 더 복잡한 것이 필요하다는 것을 알았습니다.

사용하려는 형식의 예:

gawk -vdate=$DATE -vtime=$TIME '{print date " " time $0 }' ./poolstat_original_format.txt

파일 이름에서 파생된 날짜와 시간을 이 두 변수에 사용합니다.

쉘 스크립팅에 대한 나의 이전 경험은 모두 시스템 자동화 및 문제 해결에 관한 것이었고, 텍스트 이동에 대해 이렇게 많은 실제적인 경험을 해본 적이 없었습니다. 따라서 이것이 실제로 간단한 질문이고 제가 지나치게 생각하고 있는 것이라면... 대단합니다. , 도움이 되는 의견을 보내주시면 감사하겠습니다.

추가정보를 추가하고 싶었으나 취소되었습니다.

날짜는 전달된 파일 이름에서 파생됩니다. 20121003-poolstat_serverxd1z0.txt 시간은 50줄당 4자리입니다.

poolstat가 실행될 때마다 int 필드를 반복해야 합니다. 자세한 내용은 아래를 참조하세요.

요약하자면, 변경해야 하는 유일한 필드는 다음과 같습니다.

필드 1, 파일 이름 IE: 20121003-poolstat_serverxd1z0.txt에서 파생된 8자리 날짜, 필드 2, 파일의 50줄마다 4자리 시간. 필드 3 반복 횟수는 다음과 같습니다. 4비트 시간의 비트 3과 4를 기준으로 합니다. 00-05-10-15-20-25-30-35-40-45-50-55분 운행.

01-02-03-04-05-06-07-08-09-10-11-12 반복.

남은 것은 기존 필드를 인쇄하여 한 줄에 배치한 다음 awk(또는 기타) 명령이 현재 반복을 추적하면서 다른 10개 필드를 인쇄하도록 하는 것입니다.

상황을 복잡하게 만들기 위해 헤더 행의 필드에는 3개의 새로운 필드가 필요합니다.

날짜 hhmm 정수

나머지 필드는 poolstat에서 제공하는 헤더입니다.

답변1

내 의견 질문을 소금 한 알로 받아들이면 다음과 같이 작동합니다.

awk -v date=20121105 'NF == 0 {print; next;};
  NF==15 && $2 == "id" {readvar=$1; for (i=1;i<15;i++) $i = $(i+1); NF=14; };
  NF==14 { if (block<2) block++; 
    concatvars=$1; for (i=2;i<11;i++) concatvars=concatvars " " $i;
    print "date hhmm int",concatvars,date,readvar,sprintf("%02d", block),"05"; };
  NF==10 {readvar2=$7;
    print $1,"pset 1",$1,$2,$3,$4,$5,$6,date,readvar,sprintf("%02d", block);};
  NF==15 { 
    print readvar2,$1,"pset 2",$1,$2,$3,$4,$5,$6,date,sprintf("%02d", block),$7;
    nextline=$8; for (i=9;i<15;i++) nextline=nextline " " $i; };
  NF==1 {print nextline,$1}' inputfile

답변2

블록 시작 부분에서 시간을 가져온 다음 그 뒤의 각 행에 일부 필드를 추가해야 하는 것처럼 보입니다.

귀하의 설명에 따르면 반복을 어떻게 수행해야 하는지 잘 모르겠습니다.

awk -v date=20121105 '
    NF == 1 {time = $1; intv = intv%50 + 1; next}
    $1 == "id" {print "date", "hhmm", "int", $0; next}
    NF > 0 {$1 = date OFS time OFS sprintf("%02d", intv) OFS $1}
    1
' file

출력을 더 예쁘게 만들고 싶다면 awk 명령을 다음으로 파이프하십시오.column -t

관련 정보