Wie sortiere ich nach ungeraden Zeilen und entferne dann wiederholte Werte?

7

Ich habe den folgenden Dateityp:

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

Ich habe versucht, so etwas zu bekommen:

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

Danach suchte ich nach so etwas:

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

Ich habe durch das sortHandbuch und einige Beiträge gescrollt, konnte aber nichts finden, was dazu passt. Ich habe nur sortnumerische Werte verwendet, um ungerade Linien zu erhalten ...

Lucas Farinazzo Marques
quelle

Antworten:

3

Nicht genau die Sortierreihenfolge, die Sie angezeigt haben, aber vielleicht auch richtig?

$ 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 -

BEARBEITEN:

Geben Sie die Zeilennummer ein und verwenden Sie sie als Sortierschlüssel. Sie sollte genau die Ausgabe liefern, die Sie mögen:

$ cat input.txt | paste - - | nl | sort -k2,2V -k1,1g | cut -f2- | tr "\t" "\n" | awk '{if($0 in line == 0) {line[$0]; print}}'
Flossenschwimmer
quelle
Es zeigt nicht genau, wie ich gepostet habe, aber für meinen Fall spielt es keine Rolle, vielen Dank!
Lucas Farinazzo Marques
7

Reine gawkLösung:

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

Der Trick besteht darin, die Indizes des Arrays amit Hilfe des gawkspeziellen Arrays PROCINFO von numerisch zu sortieren .

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

Übrigens, es ist schade, dass awk keine Option zum natürlichen Sortieren bietet, auch bekannt als Versionssortierung (nach Text mit Zahlen).

jimmij
quelle
3

Mit GNU sortund unter der Annahme, dass die Zeilen keine TAB-Zeichen enthalten:

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

Oder sort -t$'\t' -sk1,1Vum die ursprüngliche Reihenfolge für Einträge mit identischen ungeraden Zeilen wie in Ihrer erwarteten Ausgabe beizubehalten.

Wenn Sie nicht GNU haben sort, und unter der Annahme , die ungeraden Zeilen immer diesem Muster folgen, können Sie ersetzen sort -Vmit sort -k1.9n.

Stéphane Chazelas
quelle
2
for element in $(sed -n 'p;n' a.txt |sort -nk 1.9 |uniq |awk '{print $1}')
do
    echo $element; cat a.txt |grep -A1 $i |grep -v trans |grep -v \\\\--
done

Wobei a.txt Ihre Eingabe ist. Geprüft:

[root@megatron ~]# cat a.txt
transcr_25793 +
YAL039C -
transcr_25793 +
YAL037C-B -
transcr_20649 +
YBL100C -
transcr_7135 +
YBL029C-A -
transcr_11317 +
YBL067C -
transcr_25793 +
YAL038W +
transcr_7135 +
YBL029W +
[root@megatron ~]# for i in $(sed -n 'p;n' a.txt |sort -nk 1.9 |uniq |awk '{print $1}')
do
echo $i; cat a.txt |grep -A1 $i |grep -v trans |grep -v \\\\--
done
transcr_7135
YBL029C-A -
YBL029W +
transcr_11317
YBL067C -
transcr_20649
YBL100C -
transcr_25793
YAL039C -
YAL037C-B -
YAL038W +
[root@megatron ~]#
Zatarra
quelle
Es schien so transcr_45 Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information. transcr_193 Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information. transcr_231 Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information. transcr_282 Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information.und so weiter ... Weißt du was ich tun kann?
Lucas Farinazzo Marques
Ich korrigierte. Sie müssen | grep -v \\ - verwenden. Oder versuchen Sie einfach, den aktualisierten Code wiederzuverwenden.
Zatarra
Selbst wenn Sie Ihre Lösung und sogar die Datei mit demselben Namen genau kopieren, funktioniert es nicht ... Es wird immer der gleiche Fehler
angezeigt
Sie können es hier herunterladen: wget 54.38.222.163/sort.sh und mit sh sort.sh ausführen. Der Text muss in a.txt sein
Zatarra
0

Vor- und Nachbearbeitung mit awk; Dies setzt nicht voraus, dass auf eine transcrZeile nur eine Y*Zeile folgt. Es ist auch idempotent - seine Ausgabe könnte als Eingabe zurückgeleitet werden und es wird das gleiche Ergebnis liefern.

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 -
Mosvy
quelle
0

Gestatten Sie mir, Ihr Problem noch einmal zu wiederholen. Sie möchten wirklich zwei Operationen ausführen:

  • Sortieren Sie die ungeradzahligen ( transcr*) Zeilen nach der Nummer in der Zeile, wobei Sie die geradzahligen ( Y*) Zeilen beibehalten, die der vorherigen Zeile zugeordnet sind
  • Führen Sie alle Y*Linien zusammen, die unter identische transcr*Linien fallen

Während ich die einzeiligen Lösungen in den anderen Antworten bewundere, denke ich, dass dies komplex genug ist, um das Schreiben eines Skripts zu rechtfertigen. Sobald Sie das Skript in einer Datei gespeichert haben, können Sie es wiederverwenden und erweitern, wenn sich Ihre Anforderungen ändern.

Dieses Skript nimmt Ihre Eingabe und erzeugt Zeilen, die mit Ihrer endgültigen Ausgabe identisch sind:

#!/bin/env python

from collections import defaultdict
import fileinput
import re

def pair_lines (iterable):
    ''' Return lines two at a time '''
    args = [iterable] * 2;
    return zip(*args)

dd = defaultdict(list)
for line1,line2 in pair_lines(fileinput.input()):
    # accumulate lists of all second lines that share the same first
    # line value
    dd[line1].append(line2)

def line_index (line):
    ''' Return first substring that looks like an integer '''
    return int(re.search(r'\d+',line).group(0))

# sort by first lines and print results
for line1 in sorted(dd.keys(), key=line_index):
    print(line1, *dd[line1], end='', sep='')

Laufen Sie mit:

reorder.py input.txt > output.txt 
jskroch
quelle