SUBBEGINで始まり、SUBENDで終わるファイルがあり、その間に行がたくさんあります。 SUBBEGINとSUBENDの間に最大行数を持つセクションを取得したいと思います。このフィルタリングのためのコマンドも取得すると役に立ちます。後で使用できる1行のコマンドとスクリプト。
<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
区切り記号に設定します。したがって、レコードは1から次に<SUBEND\n
実行され、これは入力例のレコードと一致します<SUBBEGIN...<SUBEND
。これらのレコードの間に異なる内容がある場合、または1つのレコードと次のレコードの間に改行がない可能性がある場合は、<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
2つの異なるコマンドを使用して大容量ファイルを2回実行したくない場合は、次のようにします。
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に保存します。