ファイルの最長部分を見つける

ファイルの最長部分を見つける

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に保存します。

関連情報