그렇지 않은 경우 Awk NR: 항목이 없는 테이블의 섹션 헤더를 제거하는 방법

그렇지 않은 경우 Awk NR: 항목이 없는 테이블의 섹션 헤더를 제거하는 방법

매일 바뀌는 데이터를 표로 정리하려고 합니다. 30개보다 큰 항목이 있는 행만 표시하도록 표를 요약했습니다.

그러나 원본 테이블의 항목 수가 30개를 초과하지 않는 경우도 있습니다. 이런 일이 발생하면 요약에 전체 공백이 필요하지 않습니다. 그렇다면 이 섹션의 전체 헤더를 어떻게 제거할 수 있습니까?

이상적으로는 5개 섹션 모두에 항목이 없으면 어떤 줄도 인쇄되지 않아야 합니다(또는 제가 시도하는 것처럼 "없음: 30보다 큰 항목이 없습니다"라는 문자열만 인쇄되어야 합니다).

5개 부분으로 구성된 요약 테이블의 예, summary_output.txt:

=========================================================================================================
Month: Jun      

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun     

Counter Name                                06/05 14:00     06/05 13:00     06/05 12:00     06/05 11:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun      

Counter Name                                06/05 10:00     06/05 09:00     06/05 08:00     06/05 07:00
=========================================================================================================


=========================================================================================================
Month: Jun    

Counter Name                                06/05 06:00     06/05 05:00     06/05 04:00     06/05 03:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun      

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================

보시다시피, 세 번째 섹션은 Original_output.txt 파일에 30보다 큰 항목이 없기 때문에 비어 있습니다. 그러나 헤더는 여전히 존재합니다.

내 요약 코드(작동):

awk '$1=="Month:"||$1==""||$1=="Counter"||(index($1, "=")!=0)||$3>=30|| $4>=30 || $5>=30||$6>=30' original_output.txt>>summarised_output.txt

헤더를 제거해 보았습니다(작동하지 않음).

touch summarised_output_temp.txt
awk '{if ($1=="Month:"||$1==""||$1=="Counter"||(index($1, "=")!=0)||$3>=30|| $4>=30 || $5>=30||$6>=30) print $0}' original_output.txt >> summarised_output_temp.txt
if (((wc -l < summarised_output_temp.txt)==42))
then
echo "None: there is no entry larger than 30" >> summarised_output.txt
else
cat output_7_temp.txt>>summarised_output.txt
fi

시도하는 동안 오류가 발생했습니다:

line 3: ((: (wc -l output_7_temp.txt | awk {print $1})==42: syntax error: invalid arithmetic operator (error token is ".txt | awk {print $1})==42")

답변1

GNU가 있는 경우 awk다음 스크립트를 사용할 수 있습니다.

awk -v RS='={105}[^=]*={105}' 'NF{print oRT,$0} {oRT=RT}' file

헤더는 여러 줄의 레코드 구분 기호로 설정됩니다 RS. 105자 2개와 그 사이의 문자로 구성됩니다 =.

이 변수는 RT각 레코드의 레코드 구분 기호를 캡처하여 변수에 저장하고 oRT인쇄할 요소가 있으면 다음 레코드에 인쇄합니다(캡처하려면 catch 사용 NF).

답변2

다음을 포함하는 실행 가능한 스크립트 test.awk를 생성합니다.

awk '
  # { print "read " $0 }
  /^SYS/ {
    if (H) {
      if (F) {print F} else { F="\r\n\r\n"}
      print H; H=""}
    print
    next
  }
  /^./ {
    H=$0
    for (i=1; i<5; i++) {
      getline
      H = H "\r\n" $0
    }
    next
  }
' $@

그리고 달리다

test.awk original_output.txt

"/^SYS/{"는 데이터 라인을 식별하는 어떤 것으로든 대체될 수 있습니다.

답변3

이 문제는 Perl을 사용하여 다음과 같이 해결할 수 있습니다.

암호

perl -F'/^=+$/m' -lan -0777e '
   my($dashes) = /^(=+)$/m;
   shift @F; pop @F;
   while ( @F > 1 ) {
      my($h, $s) = splice @F, 0, 2;
      next if $s =~ /^(?:\h*\n)+$/;
      print join $dashes, q(), $h, $s, !@F ? q() : ();
   }
' input.txt

산출

=========================================================================================================
Month: Jun

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/05 14:00     06/05 13:00     06/05 12:00     06/05 11:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/05 06:00     06/05 05:00     06/05 04:00     06/05 03:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================

설명하다

  • 한숨에 들어갑니다: -0777선택하다진주가능하게하다.
  • 대시를 따라 전체 파일을 분할합니다(이제 하나의 긴 문자열로 처리됨)./^=+$/미터주어진 줄에 반복되는 같음만 포함된 곳이 파일을 분할하는 곳임을 의미합니다.
  • -ㅏ옵션이 만들 것이다진주분할된 부분을 배열로 채웁니다.@에프.
  • -NPerl의 옵션은 다음 레코드를 읽기 전에 자동 인쇄를 비활성화합니다.- 입력에서 읽은 레코드에 대한 루프와 유사합니다.
  • 먼저 입력에 점선을 저장합니다.
  • 분할 작업으로 인해 첫 번째 요소와 마지막 요소가 비어 있게 되므로 다음으로 시작합니다.@에프주요 작업을 수행하기 전에 배열을 수행하십시오.
  • 2개의 요소를 사용하는 while 루프를 설정합니다(접합) 언젠가부터@에프array.첫 번째는 제목이고 두 번째는 섹션입니다. 배열에 요소가 2개 이상 남아 있는 한 루프는 계속됩니다.
  • 핵심은 처리 제목/섹션 듀엣을 건너뛸지 여부를 결정하는 것입니다. 이는 섹션에 빈 줄만 포함되거나 가로 공백만 있는 줄(\시간). 정규 표현식은 다음과 같습니다./^(?:\h*\n)+$/
  • 이제 섹션이 비어 있지 않은 경우 제목/섹션 듀오를 대시와 함께 연결해야 합니다. 마지막 제목/섹션이 합쳐지면 대시를 추가하여 마무리해야 한다는 것을 기억합니다.

답변4

Olive의 답변과 유사하지만 조금 더 간단할 수도 있습니다.

gawk -v RS='=+\n' '
    NR % 2 == 0 {header = $0; next}
    /[^[:space:]]/ {printf "%s", RT header RT $0}
    END {print RT}
' output.txt 

s 줄을 =레코드 구분 기호로 사용합니다. 헤더는 모든 짝수 레코드에 대한 것입니다. "content"에 공백이 아닌 문자가 포함된 경우 "content"는 비어 있지 않습니다.

RT"레코드 구분 기호인 RS가 나타내는 텍스트와 일치하는 입력 텍스트입니다. 이는 레코드를 읽을 때마다 설정됩니다."를 포함하는 GNU awk 특정 변수입니다.

관련 정보