ファイルからキーの周りの行を抽出する

ファイルからキーの周りの行を抽出する

約1500万行の大きなファイルがあります。奇数行にはキー(キーだけでなく)も含まれ、行もデータです。つまり、ファイルは次のようになります。

WRTZ Tyrosine
1287998798
ASDF Proline
9408654860
TYSR Serine
9809804090
ASDF Cytosine
4950409808

ここでキーはASDF、、、TYSRですWRTZ

約100,000のキーリストがあります。このキーに対応するデータ(2行)を抽出したいと思います。

私が試した1つの方法は、grepキーを含む行から行番号を取得し、ループ内でおよびを使用してそのhead行と次の行を抽出することでした。tailただし、実行するのに時間がかかりそうです。

これを行うより効率的な方法はありますか?

答え1

偶数行と奇数行に変化がない場合。次に、次のコマンドを試してください。

awk 'NR%2{printf $1"-";next;}1' <Filename>

上記のコマンドの出力は次のようになります。

WRTZ-1287998798

ASDF-9408654860

TYSR-9809804090

ASDF-4950409808

答え2

小さなawkスクリプトで操作を実行できます。 awk manのマニュアルを読むとわかりやすいです。

    #!/usr/bin/awk -f
    BEGIN{got=0;linenum=0}
    /ASDF/{printf ("%s ",$1); got=1;linenum=NR+1}
    /TYSR/{printf ("%s ",$1); got=1;linenum=NR+1}
    /WRTZ/{printf ("%s ",$1); got=1;linenum=NR+1}
    /^[0-9]/{if ( ( got == 1 ) && ( linenum == NR) ) {
    printf("%s\n",$1)
    got=0
    linenum=0
    }}

出力は次のとおりです。

    ./awk_script data_file

    WRTZ 1287998798
    ASDF 9408654860
    TYSR 9809804090
    ASDF 4950409808

自分のニーズに合わせて修正できます!

答え3

grep最も望むのは、一致の周りに+/-線を表示するためのデフォルトオプションを利用することです。

   Context Line Control
       -A NUM, --after-context=NUM
              Print NUM lines of trailing context after matching lines.  Places a line containing a group separator (--)  between  contiguous
              groups of matches.  With the -o or --only-matching option, this has no effect and a warning is given.

       -B NUM, --before-context=NUM
              Print  NUM  lines of leading context before matching lines.  Places a line containing a group separator (--) between contiguous
              groups of matches.  With the -o or --only-matching option, this has no effect and a warning is given.

       -C NUM, -NUM, --context=NUM
              Print NUM lines of output context.  Places a line containing a group separator (--) between contiguous groups of matches.  With
              the -o or --only-matching option, this has no effect and a warning is given.

答え4

使用幸せ(以前のPerl_6)

ペアの行を探している場合は、次の手順を実行しrotorますbatch

~$ raku -e '.put for lines.rotor(2, partial => True).map: *.words[0,2];'  file

#OR

~$ raku -e '.put for lines.batch(2).map: *.words[0,2];'  file

Rakuのrotor/batchルーチンは、ユーザーが定義した数(例:23、4など)の要素(例lines:)を取得してグループ化できます。完全なペアが必要な場合(つまり、ファイルに偶数行が含まれている場合)、rotorこのpartial => Trueパラメータを単に使用して削除するだけです。

注:このコードは、スペースで区切られた基準に従って.words要素を保持します。たとえば、一部のペアのwords最初の行に2つがあり、他のペアの最初の行に3つ(またはそれ以上)がある場合、words問題が発生する可能性があります。

最初を選択すると、wordこの問題を回避できます。行は次のとおりです。

~$ raku -e '.put for lines.rotor(2).map( *.map: *.words[0]);'  file

#OR (using `>>` hyper notation):

~$ raku -e '.put for lines.rotor(2)>>.map: *.words[0];'  file

入力例:

WRTZ Tyrosine
1287998798
ASDF Proline
9408654860
TYSR Serine
9809804090
ASDF Cytosine
4950409808

出力例(すべてのコード例):

WRTZ 1287998798
ASDF 9408654860
TYSR 9809804090
ASDF 4950409808

https://docs.raku.org/routine/rotor
https://raku.org

関連情報