Sortieren Sie Datei B basierend auf Spalte 3 von Datei A, ohne den Inhalt von Datei A zu ändern

Sortieren Sie Datei B basierend auf Spalte 3 von Datei A, ohne den Inhalt von Datei A zu ändern

Ich habe folgende Datei:

cat fileA.txt

seattle    1991  west
atlanta    1993  west
turlock    1998  west
marysville 2004  south
newyork    2007  north
canada     2004  west

Und die zweite Datei sieht so aus:

cat fileB.txt

popular
someWhatPopular
boring
popular
popular
popular

Ich möchte folgende Ausgabe erhalten fileB.txt:

popular popular popular someWhatPopular boring popular

Im Wesentlichen versuche ich also, fileB.txtin fileA.txtdie dritte Spalte zu sortieren

Ich habe den folgenden Code ausprobiert:

   #!/bin/bash
   sort -s -k3,3 fileA.txt fileB.txt

Aber es hat nicht funktioniert. Irgendwelche Vorschläge? Ich bin ziemlich offen für alles, was keine Hardcoding erfordert. Bash/awk/sed usw.

Antwort1

Dies ist eher ein Datenstrukturproblem als ein Linux-Problem. Sie benötigen einen gemeinsamen Eintrag (Schlüssel) in beiden Tabellen, um sie zu verknüpfen, genau wie in jeder „Datenbank“, und es empfiehlt sich, in der ersten Spalte jeder Datentabelle einen eindeutigen Schlüssel zu speichern. Dann können Sie nach Herzenslust sortieren und verknüpfen.

Nehmen Sie beispielsweise @glennjackman mapping und definieren Sie den Zuordnungsschlüssel als Nord, Süd usw.

1 south somewhatPopular
2 west popular
3 north boring
4 east unexplored

in einer Datei namens file popularity. Ändern Sie es, fileAum einen eindeutigen Schlüssel einzuschließen

1 seattle    1991  west
2 atlanta    1993  west
3 turlock    1998  west
4 marysville 2004  south
5 newyork    2007  north
6 canada     2004  west

dann können Sie diese Dateien bearbeiten, indem joinSie sie auf den von Ihnen gewählten Schlüssel (in Ihrem Fall wird Spalte 2 in popularitySpalte 4 in zugeordnet fileA) sortieren, aber join beide Dateien müssen auf dem Schlüsselfeld sortiert sein, also

join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity) | sort -k2 | awk '{print $6}'

popular
popular
popular
somewhatPopular
boring
popular

Dies ist ein bisschen ein Vorschlaghammer-Ansatz, der Ihnen aber die größte Flexibilität bietet.

Unterbrechen Sie den obigen Befehl an jeder Pipe und Sie werden sehen, was jeder Schritt bewirkt.

Bearbeiten: Erklärung vonjoin -1 4 -2 2 # its in the man pages

Dies weist darauf hin join, dass man in der 4. Spalte der Tabelle 1 (-1 4) nachsehen und in der 2. Spalte der Tabelle 2 (-2 2) nach passenden Werten suchen soll.

joindann werden die Spalten aus den beiden Tabellen zu einer einzigen Tabelle zusammengefasst, wobei die Schlüsselspalte (Norden usw.) nur einmal eingefügt wird. Sehen Sie sich die Ausgabe von

join -1 4 -2 2 <(sort -k4 fileA) <(sort -k2 popularity)

und es sollte klarer sein

Da wir die Datentabellen sortieren mussten, damit das joinfunktionierte, haben wir dann

| sort -k2

die kombinierte Tabelle, um sie wieder in ihre ursprüngliche Reihenfolge zu bringen.

Die gewünschte Spalte ist Spalte 6 in der kombinierten Tabelle, also müssen wir nur

| awk '{print $6}'

zu stdout.

Antwort2

Sie könnten versuchen, pastedie beiden „Tabellen“-Dateien zusammenzufassen, die Ausgabe an weiterzuleiten sortund dann cutnur die vierte Spalte beizubehalten.

Ungetesteter (im Moment noch mit dem Handy) Versuch wäre so etwas wie

paste fileA fileB | sort -s -k3,3 | cut -f4

Antwort3

Die alphabetische Zuordnung erhalten Sie mit

paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)
north   boring
south   popular
west    someWhatPopular

Und dann kann mit awk eine Form der gewünschten Ausgabe erzeugt werden:

awk '
    NR==FNR {map[$1] = $2; next} 
    {print map[$NF]}
' <(paste <(awk '{print $NF}' fileA.txt | sort -u) <(sort -u fileB.txt)) fileA.txt
someWhatPopular
someWhatPopular
someWhatPopular
popular
boring
someWhatPopular

verwandte Informationen