0

私はfile1を持っています:

id position 
a1 21
a1 39
a1 77
b1 88
b1 122
c1 22

ファイル2

id  class  position1 position2
a1  Xfact   1           40
a1  Xred    41          66
a1  xbreak  69          89
b1  Xbreak  77          133
b1  Xred    140         199
c1  Xfact   1           15
c1  Xbreak  19          35

私はこの出力のようなものが欲しいです:

id  position  class
a1   21        Xfact
a1   39        Xfact
a1   77        Xbreak
b1   88        Xbreak
b1   122       Xbreak
c1   22        Xbreak

file1からidとpositionを出力し、file1からpositionを取得して、file2の位置と比較する単純なawkスクリプトが必要です。ファイル1の位置がファイル2の位置1と2の範囲にある場合。対応するクラスを印刷する

4

1 に答える 1

0

を使用した片道awk。単純なスクリプトではありません。プロセスを簡単に説明します。キーポイントは変数'all_ranges'です。リセットがデータを保存する範囲のファイルから読み取り、設定されると、そのプロセスを停止して 'id-position' ファイルからの読み取りを開始し、データ内の位置をチェックします配列の範囲と一致する場合は出力します。範囲のファイルを何度も処理することを避け、チャンクごとに処理することを避けようとしたため、より複雑になりました。

編集idして、両方のファイルのフィールドがソートされていると想定していることを追加します。そうしないと、このスクリプトは惨めに失敗し、別のアプローチが必要になります。

の内容script.awk:

BEGIN {
    ## Arguments:
    ## ARGV[0] = awk
    ## ARGV[1] = <first_input_argument>
    ## ARGV[2] = <second_input_argument>
    ## ARGC = 3
    f2 = ARGV[ --ARGC ];

    all_ranges = 0

    ## Read first line from file with ranges to get 'class' header.
    getline line <f2
    split( line, fields )
    class_header = fields[2];
}

## Special case for the header.
FNR == 1 {
    printf "%s\t%s\n", $0, class_header;
    next;
}

## Data.
FNR > 1 {

    while ( 1 ) {

        if ( ! all_ranges ) {

            ## Read line from file with range positions.
            ret = getline line <f2

            ## Check error.
            if ( ret == -1 ) {
                printf "%s\n", "ERROR: " ERRNO
                close( f2 );
                exit 1;
            }

            ## Check end of file.
            if ( ret == 0 ) {
                break;
            }

            ## Split line in spaces.
            num = split( line, fields )
            if ( num != 4 ) {
                printf "%s\n", "ERROR: Bad format of file " f2;
                exit 2;
            }

            range_id = fields[1];
            if ( $1 == fields[1] ) {
                ranges[ fields[3], fields[4] ] = fields[2];
                continue;
            }
            else {
                all_ranges = 1
            }
        }

        if ( range_id == $1 ) {
            delete ranges;
            ranges[ fields[3], fields[4] ] = fields[2];
            all_ranges = 0;
            continue;
        }        

        for ( range in ranges ) {
            split( range, pos, SUBSEP )
            if ( $2 >= pos[1] && $2 <= pos[2] ) {
                printf "%s\t%s\n", $0, ranges[ range ];
                break;
            }  
        }
        break;
    }
}

END {
    for ( range in ranges ) {
        split( range, pos, SUBSEP )
        if ( $2 >= pos[1] && $2 <= pos[2] ) {
            printf "%s\t%s\n", $0, ranges[ range ];
            break;
        }  
    }
}

次のように実行します。

awk -f script.awk file1 file2 | column -t

次の結果で:

id  position  class
a1  21        Xfact
a1  39        Xfact
a1  77        xbreak
b1  88        Xbreak
b1  122       Xbreak
c1  22        Xbreak
于 2012-07-20T12:06:10.163 に答える