2017-11-22 9 views
2

7列を持つファイルを変更しようとしています。 入力ファイルの例は次のとおりです。特定の列を共有する行を選択する(すべてではない)

1.txt 
    1 10 11 A L X3 -1.1 
    1 10 11 A L X1 1.1 
    1 13 21 A T X3 -2.1 
    3 11 12 A T X2 -3.1 
    3 11 12 K T X2 7.1 
    4 11 12 A T X7 -8.1 
    4 11 12 C T X7 -8.1 
    4 11 12 C T X7 11.1 

は、私が最初の5列を共有しますが、最後の二つが異なるとも最初の5列を共有していない他人れ、これらの行を抽出したいです。そして、最後の列の値が最も低い行を保持したい。

予想される出力は次のようになります。それは1.txtファイルに2.lineとの最初の5列を共有しているため

1 10 11 A L X3 -1.1 
    1 13 21 A T X3 -2.1 
    3 11 12 A T X2 -3.1 
    3 11 12 K T X2 7.1 
    4 11 12 A T X7 -8.1 
    4 11 12 C T X7 -8.1 

1st lineはこちらです。最後の列(-1.1 < 1.1)の番号が最も低く、最後の行ではという文字列を11.1よりも小さく保持しているので、それだけを保持し、他の行は同一ではないようにします最初に5のフィールドがあります。 私が試みたのは、最初の5列をindexとしてawkに保存していますが、それ以外のものは印刷しないでください。そして、最後の列の番号が最も小さい行を選択しません。 コード:

awk -F"\t" '!seen[$1,$2,$3,$4,$5]++' 1.txt 

その出力:

1 10 11 A L X3 -1.1 
1 10 11 A L X1 1.1 
1 13 21 A T X3 -2.1 
3 11 12 A T X2 -3.1 
3 11 12 K T X2 7.1 
4 11 12 A T X7 -8.1 
4 11 12 C T X7 -8.1 
4 11 12 C T X7 11.1 

私は最後の列の最小値を持つ最初の5列を、共有している行を選択することはできません。 ご協力いただき誠にありがとうございます。

答えて

1
$ sort -k1,5 -k7n file | rev | uniq -f2 | rev 
awk ' 
    {key = $1 FS $2 FS $3 FS $4 FS $5} 
    !(key in min) || $NF < min[key] {min[key] = $NF; line[key] = $0} 
    END {for (key in line) print line[key]} 
' file 
1 10 11 A L X3 -1.1 
    1 13 21 A T X3 -2.1 
    4 11 12 C T X7 -8.1 
    4 11 12 A T X7 -8.1 
    3 11 12 K T X2 7.1 
    3 11 12 A T X2 -3.1 

ことなく別のアプローチである出力の順序が不定であることに注意してください。出力は常にsortにパイプするか、GNU awkを使用してarray traversalを制御してください。


私はちょうどline配列が完全に不要であるが、大量のメモリを消費します実現:min配列は、それ値としてキーと第六フィールドとして最初の5つの分野

awk ' 
    {key = $1 FS $2 FS $3 FS $4 FS $5} 
    !(key in min) || $NF < min[key] {min[key] = $NF} 
    END {for (key in line) print key, min[key]} 
' file 

を保持しています交換のために時間がかかるかもしれません。

+0

最後の列の値に応じてどのように選択しましたか?説明することは可能でしょうか? – bapors

+1

私は最後の列の最小値を記録します: '$ NF

+0

ありがとう!それを速くする方法はありますか?私の入力ファイルは膨大で、時間がかかります。 – bapors

3

awkレスキュー!

$ sort -k1,5 -k7n file | 
    awk '!a[$1,$2,$3,$4,$5]++' 


1 10 11 A L X3 -1.1 
1 13 21 A T X3 -2.1 
3 11 12 A T X2 -3.1 
3 11 12 K T X2 7.1 
4 11 12 A T X7 -8.1 
4 11 12 C T X7 -8.1 

ソートグループ共有鍵を持つレコード(項目1〜5)と7番目のフィールドによってそれらをランク付けする数値(第1のいずれかが最小値である)昇順(sortの助けを借りて)。 awkにパイプして、指定されたキー(有名なawkイディオム、あなたのスクリプトでも使用されています)の最初のレコードを取得します。ここ

awk

+0

少し説明してもらえますか? – bapors

+0

しかし、たとえば、最初の連続する列ではなく、列1と4と5でソートする場合は、どうすればいいですか? – bapors

+0

キーが連続していない場合、 'uniq'ソリューションは動作しません。 'sort/awk'のペアは両方のキーを正しく設定すると動作します。 – karakfa

関連する問題