IT-Swarm.Net

Gibt es eine Möglichkeit, Headerzeilen in einer UNIX-Sortierung zu ignorieren?

Ich habe eine Datei mit einem Feld mit fester Breite, die ich mithilfe des UNIX-Sortierprogramms (in meinem Fall Cygwin) sortieren möchte.

Das Problem ist, dass sich oben in der Datei eine zweizeilige Kopfzeile befindet, die am Ende der Datei sortiert wird (da jede Kopfzeile mit einem Doppelpunkt beginnt).

Gibt es eine Möglichkeit, sort zu sortieren, entweder "die ersten beiden Zeilen über unsortiert übergeben" oder eine Reihenfolge angeben, die die Doppelpunktzeilen nach oben sortiert - die restlichen Zeilen beginnen immer mit einer 6-stelligen Zahl (die eigentlich der Schlüssel I ist) bin am sortieren) wenn das hilft.

Beispiel:

:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
500123TSTMY_RADAR00
222334NOTALINEOUT01
477821USASHUTTLES21
325611LVEANOTHERS00

sollte sortieren nach:

:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
222334NOTALINEOUT01
325611LVEANOTHERS00
477821USASHUTTLES21
500123TSTMY_RADAR00
80
Rob Gilliam
(head -n 2 <file> && tail -n +3 <file> | sort) > newfile

Mit den Klammern wird eine Subshell erstellt, die den Standardauszug umschließt, sodass Sie ihn per Pipe oder umleiten können, als ob er von einem einzelnen Befehl stammen würde.

92
BobS

Schnelles, zuverlässiges und kostengünstiges Cloud-Hosting

Registrieren Sie sich und erhalten Sie innerhalb von 30 Tagen einen Bonus von $50!

Wenn Sie nichts dagegen haben, awk zu verwenden, können Sie die integrierten Pipe-Fähigkeiten von awk nutzen

z.B.

extract_data | awk 'NR<3{print $0;next}{print $0| "sort -r"}' 

Dies druckt die ersten beiden Zeilen wörtlich und leitet den Rest durch sort.

Beachten Sie, dass dies den besonderen Vorteil hat, dass Sie Teile .__ einer Pipe-Eingabe selektiv sortieren können. Bei allen anderen vorgeschlagenen Methoden werden nur einfache Dateien sortiert, die mehrmals gelesen werden können. Das funktioniert bei allem.

41
Dave

Hier ist eine Version, die mit Pipe-Daten funktioniert:

(read -r; printf "%s\n" "$REPLY"; sort)

Wenn Ihre Kopfzeile mehrere Zeilen enthält:

(for i in $(seq $HEADER_ROWS); do read -r; printf "%s\n" "$REPLY"; done; sort)

Diese Lösung ist von hier

26
freeseek

Sie können tail -n +3 <file> | sort ... verwenden (tail gibt den Dateiinhalt der 3. Zeile aus).

6
Anton Kovalenko
head -2 <your_file> && nawk 'NR>2' <your_file> | sort

beispiel:

> cat temp
10
8
1
2
3
4
5
> head -2 temp && nawk 'NR>2' temp | sort -r
10
8
5
4
3
2
1
4
Vijay

In einfachen Fällen kann sed die Arbeit elegant erledigen:

    your_script | (sed -u 1q; sort)

oder gleichwertig,

    cat your_data | (sed -u 1q; sort)

Der Schlüssel befindet sich im 1q - Erste Zeile (Kopfzeile) drucken und beenden (den Rest der Eingabe auf sort belassen).

Für das gegebene Beispiel wird 2q den Trick machen.

Der Schalter -u (ungepuffert) ist für diejenigen seds (insbesondere GNUs) erforderlich, die andernfalls die Eingabe in Blöcken lesen und dabei Daten verbrauchen würden, die Sie stattdessen sort durchlaufen möchten.

1
Andrea

Es dauert nur 2 Zeilen Code ...

head -1 test.txt > a.tmp; 
tail -n+2 test.txt | sort -n >> a.tmp;

Für numerische Daten ist -n erforderlich. Für die Alpha-Sortierung ist die Option -n nicht erforderlich.

Beispieldatei:
$ cat test.txt

header
8
5
100
1
-1 

Ergebnis:
$ cat a.tmp

header
-1
1
5
8
100

1
Ian Sherbin

Dies ist die gleiche Antwort von Ian Sherbin, aber meine Implementierung ist: -

cut -d'|' -f3,4,7 $arg1 | uniq > filetmp.tc
head -1 filetmp.tc > file.tc;
tail -n+2 filetmp.tc | sort -t"|" -k2,2 >> file.tc;
0
Bik

Hier ist eine bash-Shell-Funktion, die von den anderen Antworten abgeleitet wurde. Es behandelt sowohl Dateien als auch Pipes. Erstes Argument ist der Dateiname oder '-' für stdin. Die restlichen Argumente werden an die Sortierung übergeben. Einige Beispiele:

$ hsort myfile.txt
$ head -n 100 myfile.txt | hsort -
$ hsort myfile.txt -k 2,2 | head -n 20 | hsort - -r

Die Shell-Funktion:

hsort ()
{
   if [ "$1" == "-h" ]; then
       echo "Sort a file or standard input, treating the first line as a header.";
       echo "The first argument is the file or '-' for standard input. Additional";
       echo "arguments to sort follow the first argument, including other files.";
       echo "File syntax : $ hsort file [sort-options] [file...]";
       echo "STDIN syntax: $ hsort - [sort-options] [file...]";
       return 0;
   Elif [ -f "$1" ]; then
       local file=$1;
       shift;
       (head -n 1 $file && tail -n +2 $file | sort $*);
   Elif [ "$1" == "-" ]; then
       shift;
       (read -r; printf "%s\n" "$REPLY"; sort $*);
   else
       >&2 echo "Error. File not found: $1";
       >&2 echo "Use either 'hsort <file> [sort-options]' or 'hsort - [sort-options]'";
       return 1 ;
   fi
}
0
JonDeg

Hier ist also eine Bash-Funktion, bei der die Argumente genau der Sortierung entsprechen. Unterstützende Dateien und Pipes.

function skip_header_sort() {
    if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then
        local file=${@: -1}
        set -- "${@:1:$(($#-1))}"
    fi
    awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file
}

Wie es funktioniert. Diese Zeile prüft, ob mindestens ein Argument vorhanden ist und ob das letzte Argument eine Datei ist.

    if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then

Dies speichert die Datei als separates Argument. Da werden wir gerade das letzte Argument löschen.

        local file=${@: -1}

Hier entfernen wir das letzte Argument. Da wollen wir es nicht als Sortierargument weitergeben.

        set -- "${@:1:$(($#-1))}"

Zum Schluss führen wir den awk-Teil aus, übergeben die Argumente (minus dem letzten Argument, falls es sich um die Datei handelt), um in awk zu sortieren. Dies wurde ursprünglich von Dave vorgeschlagen und für Sortierargumente modifiziert. Wir verlassen uns auf die Tatsache, dass $file leer ist, wenn wir pfeifen und somit ignoriert werden.

    awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file

Verwendungsbeispiel mit einer durch Kommas getrennten Datei.

$ cat /tmp/test
A,B,C
0,1,2
1,2,0
2,0,1

# SORT NUMERICALLY SECOND COLUMN
$ skip_header_sort -t, -nk2 /tmp/test
A,B,C
2,0,1
0,1,2
1,2,0

# SORT REVERSE NUMERICALLY THIRD COLUMN
$ cat /tmp/test | skip_header_sort -t, -nrk3
A,B,C
0,1,2
2,0,1
1,2,0
0
flu

Mit Python:

import sys
HEADER_ROWS=2

for _ in range(HEADER_ROWS):
    sys.stdout.write(next(sys.stdin))
for row in sorted(sys.stdin):
    sys.stdout.write(row)
0
crusaderky