파일의 가장 긴 부분 찾기

파일의 가장 긴 부분 찾기

SUBBEGIN으로 시작하고 SUBEND로 끝나는 파일이 있는데 그 사이에 줄이 많이 있습니다. SUBBEGIN과 SUBEND 사이에 최대 행 수가 있는 섹션을 가져오고 싶습니다. 이 필터링에 대한 명령도 얻으면 도움이 될 것입니다. 나중에 사용할 수 있는 한 줄 명령 및 스크립트입니다.

<SUBBEGIN
        IMSI=XXXXXXXX;
        MSISDN=XXXXXXXXXXXX;
        DEFCALL=TS11;
        CURRENTNAM=BOTH;
        CAT=COMMON;
        TBS=TS11&TS12&TS21&TS22&TS61&BS26&BS2G;
        ODBIC=BAIC;
        ODBOC=BAOC;
<SUBEND
<SUBBEGIN
        IMSI=XXXXXXXX;
        MSISDN=XXXXXXXXXXXX;
        DEFCALL=TS11;
        CURRENTNAM=BOTH;
<SUBEND

원하시는 내용은 다음과 같습니다

<SUBBEGIN
        IMSI=XXXXXXXX;
        MSISDN=XXXXXXXXXXXX;
        DEFCALL=TS11;
        CURRENTNAM=BOTH;
        CAT=COMMON;
        TBS=TS11&TS12&TS21&TS22&TS61&BS26&BS2G;
        ODBIC=BAIC;
        ODBOC=BAOC;
<SUBEND

추천해주세요! !

답변1

GNU 사용 awk:

gawk -v 'RS=<SUBEND\n' -v ORS= -F'\n' '
  NF > max {max = NF; ret = $0 RT}
  END      {if (max) print ret}'

여기서는 <SUBEND개행 문자를 R에코 S구분 기호로 설정합니다. 따라서 레코드는 하나에서 <SUBEND\n다음으로 실행되며 이는 입력 예제의 레코드와 일치합니다 <SUBBEGIN...<SUBEND. 이러한 레코드 사이에 다른 내용이 있거나 한 레코드와 다음 레코드 사이에 줄 바꿈이 없을 수 있는 경우 <SUBBEGIN...<SUBEND메서드를 조정해야 합니다.<SUBEND<SUBBEGIN

예를 들어:

gawk -v 'RS=<SUBEND' -F'\n' '
  !(RT && sub(/.*<SUBBEGIN/, "<SUBBEGIN")) {next}
  NF > max {max = NF; ret = $0 RT}
  END      {if (max) print ret}'

답변2

사용 awk:

awk '
  {lines[NR]=$0}
  $0 == "<SUBBEGIN" {start=NR}
  $0 == "<SUBEND" && (NR-start) > subsize {substart=start; subsize=(NR-start)} 
  END{for (i=substart; i<=(substart+subsize);i++) print lines[i]}
' file
  • {lines[NR]=$0}- 모든 행을 배열에 저장
  • $0 == "<SUBBEGIN" {start=NR}"sub" 시작 부분에 줄 번호 저장
  • $0 == "<SUBEND" && (NR-start) > subsize {substart=start; subsize=(NR-start)}"sub"가 끝나고 지금까지 가장 긴 "sub"일 때 substart변수를 저장합니다 subsize.
  • END{for (i=substart; i<=(substart+subsize);i++) print lines[i]}- 저장된 배열에서 subsize행을 인쇄합니다.substart

답변3

다음을 시작점으로 사용해 보세요.

awk '
/<SUBBEGIN/     {NRBEGIN   = NR
                 IMSIFOUND = 0
                }
/<SUBEND/       {if (IMSIFOUND) {DELTA = NR - NRBEGIN
                                 if (DELTA > DLMX)      {DLMX = DELTA
                                                         NRMX = NRBEGIN
                                                        }
                                }
                }
/IMSI/          {IMSIFOUND = 1
                }
END             {print NRMX ",+" DLMX "p"
                }
' file |  sed -nf- file
        IMSI=XXXXXXXX;
        MSISDN=XXXXXXXXXXXX;
        DEFCALL=TS11;
        CURRENTNAM=BOTH;
        CAT=COMMON;
        TBS=TS11&TS12&TS21&TS22&TS61&BS26&BS2G;
        ODBIC=BAIC;
        ODBOC=BAOC;
<SUBEND

"IMSI"가 사이에 있으면 가장 큰 블록의 시작 및 끝 줄 번호를 기록하고 해당 줄을 인쇄하는 해당 섹션에 END작은 스크립트를 인쇄합니다 .sed

두 가지 다른 명령을 사용하여 대용량 파일을 두 번 실행하고 싶지 않다면 다음을 시도하십시오.

awk '
/<SUBBEGIN/     {delete WIP
                 CNT = IMSIFOUND = 0
                }
                {WIP[++CNT] = $0
                }
/<SUBEND/       {if (IMSIFOUND) {if (CNT > MAX) {for (i=1; i<=CNT; i++) BLOCK[i] = WIP[i]
                                                 MAX   = CNT
                                                }
                                }
                }
/IMSI/          {IMSIFOUND = 1
                }
END             {for (i=1; i<=MAX; i++) print BLOCK[i]
                }
' file5
<SUBBEGIN
        IMSI=XXXXXXXX;
        MSISDN=XXXXXXXXXXXX;
        DEFCALL=TS11;
        CURRENTNAM=BOTH;
        CAT=COMMON;
        TBS=TS11&TS12&TS21&TS22&TS61&BS26&BS2G;
        ODBIC=BAIC;
        ODBOC=BAOC;
<SUBEND

답변4

sed여기에 표시된 것처럼 확장 정규식 모드(-E)의 GNU sed를 사용하여 이 작업을 수행할 수 있습니다.

B='<SUBBEGIN'
E='<SUBEND'

sed -E "/\n/q
  /^$B\$/!d
  s/^/\n/
  :loop
    N;s/^/_/
  /\n$E\$/!bloop
  G;ta;:a
  /^(_+)(\n$B\n).*\n\1_+\2/!s/(\n$E)\n.*/\1/
  tupdt
  g;:updt
  h;\$D;d
" file

계획은 다음과 같습니다.

  • 읽은 각 줄의 시작 부분에 밑줄을 표시합니다.
  • 블록 시작 다음에 오는 밑줄의 길이를 비교해보겠습니다.
  • 패턴 공간에 블록을 축적합니다.
  • 홀드를 패턴 공간에 붙여넣습니다.
  • 패턴 공간 블록 밑줄이 더 길거나 Hold와 동일한 경우에만 새 블록을 Hold에 저장합니다.

관련 정보