奇数行で並べ替えて重複値を削除するにはどうすればよいでしょうか?

奇数行で並べ替えて重複値を削除するにはどうすればよいでしょうか?

次の種類のファイルがあります:

transcr_25793 +
YAL039C -
transcr_25793 +
YAL037C-B -
transcr_20649 +
YBL100C -
transcr_7135 +
YBL029C-A -
transcr_11317 +
YBL067C -
transcr_25793 +
YAL038W +
transcr_7135 +
YBL029W +

私は次のようなものを取得しようとしていました:

transcr_7135 +
YBL029C-A -
transcr_7135 +
YBL029W +
transcr_11317 +
YBL067C -
transcr_20649 +
YBL100C -
transcr_25793 +
YAL039C -
transcr_25793 +
YAL037C-B -
transcr_25793 +
YAL038W +

その後、私は次のようなものを探していました。

transcr_7135 +
YBL029C-A -
YBL029W +
transcr_11317 +
YBL067C -
transcr_20649 +
YBL100C -
transcr_25793 +
YAL039C -
YAL037C-B -
YAL038W +

マニュアルやいくつかの投稿をスクロールしてみましたsortが、これに近いものは見つかりませんでした。sort数値を使用して奇数の行を取得するだけです...

答え1

純粋なgawkソリューション:

awk -F_ 'NR%2{i=$2;next}{a[i]=a[i]"\n"$0}
         END{PROCINFO["sorted_in"]="@ind_num_asc";
             for(i in a) printf "%s","transcr_"i""a[i]"\n"}' file

秘訣は、PROCINFO 特殊配列aを少し利用して、配列のインデックスを数値的にソートすることです。gawk

transcr_7135
YBL029C-A -
YBL029W +
transcr_11317
YBL067C -
transcr_20649
YBL100C -
transcr_25793
YAL039C -
YAL037C-B -
YAL038W +

ところで、awkには自然にソートするオプションがないのは残念です。バージョンソート(数字の付いたテキストに従って)。

答え2

まさにあなたが示した並び順ではありませんが、おそらく正しいでしょうか?

$ cat input.txt|paste - -| sort -k1,1V -k2,2| tr "\t" "\n" | awk '{if($0 in line == 0) {line[$0]; print}}'
    transcr_7135 +
    YBL029C-A -
    YBL029W +
    transcr_11317 +
    YBL067C -
    transcr_20649 +
    YBL100C -
    transcr_25793 +
    YAL037C-B -
    YAL038W +
    YAL039C -

編集:

行番号を挿入し、それをソートキーとして使用すると、希望どおりの出力が生成されます。

$ cat input.txt | paste - - | nl | sort -k2,2V -k1,1g | cut -f2- | tr "\t" "\n" | awk '{if($0 in line == 0) {line[$0]; print}}'

答え3

GNU ではsort、行にタブ文字が含まれていないと仮定します。

paste - - < file | sort -V | tr '\t' '\n' | awk '!seen[$0]++'

または、sort -t$'\t' -sk1,1V予想される出力のように、同一の奇数行を持つエントリの元の順序を保持します。

GNU をお持ちでない場合sort、奇数行が常にそのパターンに従うと仮定すると、sort -Vを に置き換えることができますsort -k1.9n

答え4

による前処理と後処理。これは、行の後に 1 行だけが続くことawkを想定していません。また、べき等性もあります。つまり、出力を入力としてパイプし直すことができ、同じ結果が得られます。transcrY*

awk '{print $0~/^transcr/ ? t=$0 : t" "$0}' /tmp/foo | sort -t_ -k2n -k2 -u | awk '{print (NF > 2) ? $3" "$4 : $0}'
transcr_7135 +
YBL029C-A -
YBL029W +
transcr_11317 +
YBL067C -
transcr_20649 +
YBL100C -
transcr_25793 +
YAL037C-B -
YAL038W +
YAL039C -

関連情報