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에 저장합니다.