0

.txt ファイルに入力していますが、

10000030
10000029
10000028
10000027
10000026
10000024
10000023
10000021
10000018
10000018
10000017
10000016
10000015
10000014
10000013
10000011
10000010
10000009
10000008
10000006
10000005
10000004
10000003
10000002
10000001

次のように、連続する入力をグループ化する必要があります。

10000001,10000006,6
10000008,10000011,4
10000013,10000019,7
10000021,10000021,1
10000023,10000024,2
10000026,10000030,5

このスクリプトを解決するのを手伝ってください.....

4

1 に答える 1

2

まず最初に、入力データにタイプミスがあるようです。10000018必要な出力を得るには、最初に10000019.

それが修正されたら、ソートされたファイルを次のawkスクリプトに渡すことで、目的の出力を取得できます。

NR==1 {
    first = $0;
    last = $0;
    prev = $0;
    count = 1;
    next;
}
$0 == prev+1 {
    last = $0;
    prev = $0;
    count++;
    next;
}
{
    print first","last","count;
    first = $0;
    last = $0;
    prev = $0;
    count = 1;
}
END {
    if (count > 0) {
        print first","last","count
    }
}

そのスクリプトdata.awkを呼び出してデータを に配置するdata.inと、結果は次のようになります。

pax> sort data.in | awk -f data.awk
10000001,10000006,6
10000008,10000011,4
10000013,10000019,7
10000021,10000021,1
10000023,10000024,2
10000026,10000030,5

awkスクリプトの仕組みについて詳しく説明します。最初の入力行についてはNR == 1、現在の値をfirstlastおよびprev(シーケンスの開始、シーケンスの終了、およびシーケンスを監視するための前の行) に格納するだけです。また、現在のカウントを に設定し1、2 番目の行を処理するために戻ります。ライン。

後続のすべての行で、$0 == prev+1現在の行が前の行よりも 1 つ多い場合、2 番目のセクションが起動します。その場合、lastとのprev値とインクリメントを更新するだけcountで、先頭に戻って次の行を処理します。

したがって、3 番目のセクションは、最初の 2 つのセクションでキャプチャされないすべてのケースに対して発生します。これは、行が 1 と前の行ではない入力ファイルの最初のレコード以外のレコードです。つまり、新しいシーケンスを開始するとき。最初に最新のシーケンスの詳細を出力し、次に最初のセクションで行ったことを複製します。

このENDセクションは、最終シーケンスの詳細を出力するために必要なすべての行が処理された後に起動します。countがゼロより大きい場合にのみ出力されることに注意してください。count ゼロの場合、ファイルは空であり、シーケンスはまったくありませんでした。


いくつかの追加条件、行の結合、およびセクションが順番に処理されるという事実に依存する、わずかに短いバリアントもあります。

NR > 1 && $0 == prev+1 {
    last = $0; prev = $0; count++;
    next;
}
{
    if (NR != 1) { print first","last","count; }
    first = $0; last = $0; prev = $0; count = 1;
}
END {
    if (count > 0) { print first","last","count }
}

そしてもちろん、非常に短い (そしてはるかに読みにくい) コマンド ライン バリアント:

pax> sort data.in | awk 'NR>1&&$0==pr+1{ls=$0;pr=$0;ct++;next}{if(NR!=1){print fr","ls","ct}fr=$0;ls=$0;pr=$0;ct=1}END{if(ct>0){print fr","ls","ct}}'
10000001,10000006,6
10000008,10000011,4
10000013,10000019,7
10000021,10000021,1
10000023,10000024,2
10000026,10000030,5
于 2013-09-15T06:10:32.220 に答える