Angenommen, ich habe eine Datei so strukturiert
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/zz/Books/Author-Zigniwe-Hisory-Medicine.pdf
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
Ich hätte gerne eine folgendermaßen sortierte Datei:
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/zz/Books/Author-Zigniwe-History-Medicine.pdf
Das heißt, alphabetisch nach der ZeichenfolgeAuthor-...
Wie Sie sehen, Author-...
ist die Position nicht konstant.
Wie kann ich das machen?
Antwort1
Versuchen Sie den folgenden bash
Befehl:
sort -t- -d -k2 -o output.txt input.txt
Es gibt vier Optionen plus den Namen der Eingabedatei input.txt
. Wenn sich diese Datei nicht im aktuellen Verzeichnis befindet, müssen Sie sie angeben path/to/the/folder/input.txt
. Die Optionen und ihre Argumente lauten wie folgt:
- -t markiert den Feldtrenner. Wir verwenden
-
als Trennzeichen, sodass alles davor und danach als-
separate Spalten betrachtet wird. - -d gibt die Wörterbuchsortierung an. Beispielsweise steht Apple vor Berry.
- -k2 gibt die Spalte an, nach der sortiert werden soll, in diesem Fall die zweite Spalte. Beachten Sie, dass die erste Spalte alles vor der ersten ist
-
. Zum Beispiel/home/zz/BOOKS/Author
. Die zweite Spalte liegt zwischen der ersten und der zweiten-
, alsoArtemis
. - -o
output.txt
leitet die sortierte Ausgabe in eine Datei statt an das Terminal um.
Hoffe das hilft
Antwort2
Obwohl es für das vorliegende Beispiel übertrieben ist, weilLösung vorgeschlagen in der Antwort von user68186, Sie könnten allgemeiner so etwas in GNU awk tun:
gawk -F/ '
function mycmp(i1,v1,i2,v2) {
m = split(v1,a);
n = split(v2,b);
return a[m]"" > b[n]"" ? 1 : a[m]"" < b[n]"" ? -1 : 0
}
{
lines[NR] = $0
}
END {
PROCINFO["sorted_in"] = "mycmp";
for(i in lines) print lines[i]
}
' file
Beachten Sie, dass nach dem lexikalischen Wert von allem nach dem letzten sortiert wird /
. Wenn das Format Author-<author name>-<title>.<extension>
also
- die feste Zeichenfolge
Author-
(die keine Auswirkung hat, da sie für alle Zeilen das gleiche Gewicht hat); dann <author name>-
; Dann<title>.
; Dann<extension>
Dies ähnelt der Funktionsweise sort
des einfachen KEYDEF von GNU -t- -k2
, d. h. der effektive Sortierschlüssel beginnt <author name>
und reicht bis zum Zeilenende.
Ein explizites Trennzeichen wird bei den split
Aufrufen weggelassen, sodass sie den Wert von erben FS
. Dies erleichtert die Änderung für Systeme, die ein anderes Pfadtrennzeichen verwenden. Die angehängten leeren Zeichenfolgen ""
in der mycmp
Funktion erzwingen einen lexikalischen Vergleich, selbst wenn die Dateinamen numerisch sind - siehe beispielsweiseWie awk zwischen Zeichenfolgen und Zahlen konvertiert
Wenn Sie lieber beim sort
Befehl bleiben möchten, können Sie GNU awk's nutzenZweiwegekommunikation mit einem anderen ProzessZu:
- dupliziere das letzte
/
-getrennte Feld am Anfang der Zeichenfolge - Übergeben Sie das Ergebnis an einen
sort
Befehl - das Sortierergebnis zurücklesen, das doppelte Präfix entfernen und drucken
dh
gawk -F/ '
BEGIN {OFS=FS; cmd = "sort -d"}
{print $NF $0 |& cmd}
END {
close(cmd,"to");
while(cmd |& getline){$1 = ""; print};
close(cmd,"from")
}
' file
Hier wird ein bisschen geschummelt, da die absoluten Pfade (Zeilen beginnen mit /
) ein anfängliches leeres Feld implizieren. Um relative Pfade verarbeiten zu können, müssten Sie zu ändern, print $NF $0
um das „fehlende“ Trennzeichen einzufügen, und dann vielleicht einen regulären Ausdruck anstelle der einfacheren Methode print $NF,$0
verwenden, um das führende Element zu entfernen.sub()
$1 = ""
Dies ist nicht nur potenziell schneller/speichereffizienter als die reine gawk
Lösung, sondern ermöglicht auch sort
das einfache Hinzufügen weiterer Optionen, z. B. cmd = "sort -d -t " FS " -k1,1r"
.