Ich habe eine Datei, die so aussieht:
AE United Arab Emirates
AG Antigua & Barbuda
AN Netherlands Antilles
AS American Samoa
BA Bosnia and Herzegovina
BF Burkina Faso
BN Brunei Darussalam
Und ich möchte die Reihenfolge umkehren und zuerst alles außer 1 $ und dann 1 $ drucken:
United Arab Emirates AE
Wie kann ich den Trick "Alles außer Feld 1" machen?
Antworten:
Zuweisen von
$1
Werken, aber es bleibt ein führender Raum:awk '{first = $1; $1 = ""; print $0, first; }'
Sie können auch die Anzahl der Spalten
NF
in einer Schleife ermitteln und diese verwenden.quelle
awk {'first = $1; $1=""; print $0'}|sed 's/^ //g'
$1=""
Lässt ein Leerzeichen, wie Ben Jackson erwähnt hat. Verwenden Sie also einefor
Schleife:Wenn Ihre Zeichenfolge also "eins zwei drei" war, lautet die Ausgabe:
zwei
drei
Wenn Sie das Ergebnis in einer Zeile wünschen, können Sie wie folgt vorgehen:
Dies gibt Ihnen: "zwei drei"
quelle
awk '{for(i=2;i<=NF;i++){ printf("%s",( (i>2) ? OFS : "" ) $i) } ; print ;}'
welche: Felder 2 bis NF drucken, nach Bedarf den Ausgabefeldtrenner hinzufügen (dh außer vor $ 2). Beim letzten Druck wird eine letzte neue Zeile hinzugefügt, um den aktuellen Zeilendruck zu beenden. Das wird funktionieren, wenn Sie FS / OFS ändern (dh es wird nicht immer "Leerzeichen" sein)Verwenden Sie den
cut
Befehl mit der--complement
Option:quelle
echo a b c | cut -d' ' -f 2-
ist eine AlternativeVielleicht der prägnanteste Weg:
Erläuterung:
$(NF+1)=$1
: Generator eines "neuen" letzten Feldes.$1=""
: Setzen Sie das ursprüngliche erste Feld auf nullsub(FS,"")
: Nach den ersten beiden Aktionen wird{$(NF+1)=$1;$1=""}
das erste Feldtrennzeichen mithilfe von sub entfernt. Der endgültige Druck ist implizit.quelle
Entfernen Sie das erste Feld und das Trennzeichen und drucken Sie das Ergebnis (
7
ist ein Wert ungleich Null, drucken Sie also $ 0).quelle
1
? Ich frage mich, wie dieses Muster verwendet wird und wollte das verstehen. Vielen Dank!Wenn Sie das erste Feld so
""
einstellen, dassOFS
zu Beginn eine einzelne Kopie von übrig bleibt$0
. Angenommen, esOFS
handelt sich nur um ein einzelnes Zeichen (standardmäßig handelt es sich um ein einzelnes Leerzeichen), können wir es mit entfernensubstr($0, 2)
. Dann hängen wir die gespeicherte Kopie von an$1
.quelle
Wenn Sie offen für eine Perl-Lösung sind ...
ist eine einfache Lösung mit einem Eingabe- / Ausgabetrennzeichen aus einem Raum, die Folgendes erzeugt:
Das nächste ist etwas komplexer
und nimmt an, dass das Eingabe- / Ausgabetrennzeichen zwei Leerzeichen ist:
Diese Befehlszeilenoptionen werden verwendet:
-n
Schleife um jede Zeile der Eingabedatei, drucke nicht automatisch jede Zeile-l
Entfernt Zeilenumbrüche vor der Verarbeitung und fügt sie anschließend wieder hinzu-a
Autosplit-Modus - Teilen Sie die Eingabezeilen in das @ F-Array. Standardmäßig wird auf Leerzeichen aufgeteilt-F
Autosplit-Modifikator, in diesem Beispiel auf '' aufgeteilt (zwei Leerzeichen)-e
Führen Sie den folgenden Perl-Code aus@F
ist das Array von Wörtern in jeder Zeile, indiziert beginnend mit 0$#F
ist die Anzahl der Wörter in@F
@F[1..$#F]
ist ein Array-Slice von Element 1 bis zum letzten Element@F[1..$#F,0]
ist ein Array-Slice von Element 1 bis zum letzten Element plus Element 0quelle
Das Feldtrennzeichen in gawk kann (zumindest) sowohl eine Zeichenfolge als auch ein Zeichen sein (es kann auch eine Regex sein). Wenn Ihre Daten konsistent sind, funktioniert dies:
Das sind zwei Leerzeichen zwischen den doppelten Anführungszeichen.
quelle
awk '{ tmp = $1; sub(/^[^ ]+ +/, ""); print $0, tmp }'
quelle
Verschieben wir alle Datensätze zum nächsten und setzen den letzten als ersten:
Erläuterung
a=$1
Speichern Sie den ersten Wert in einer temporären Variablen.for (i=2; i<=NF; i++) $(i-1)=$i
Speichern Sie den N-ten Feldwert im (N-1) -ten Feld.$NF=a
Speichern Sie den ersten Wert ($1
) im letzten Feld.{}1
wahre Bedingung,awk
um die Standardaktion auszuführen :{print $0}
.Auf diese Weise ist das Ergebnis auch gut, wenn Sie zufällig ein anderes Feldtrennzeichen haben:
quelle
Ein erster Versuch scheint für Ihren speziellen Fall zu funktionieren.
quelle
Option 1
Es gibt eine Lösung, die mit einigen Versionen von awk funktioniert:
Erläuterung:
Ergebnis:
Dies kann jedoch bei älteren Versionen von awk fehlschlagen.
Option 2
Das ist:
Beachten Sie, dass das OFS gelöscht werden muss, nicht das FS. Die Zeile wird neu berechnet, wenn das Feld $ 1 zugewiesen wird. Dadurch werden alle FS-Läufe in einen OFS geändert.
Aber selbst diese Option schlägt bei mehreren Trennzeichen immer noch fehl, wie die Änderung des OFS deutlich zeigt:
Diese Zeile gibt Folgendes aus:
Dies zeigt, dass FS-Läufe in einen OFS geändert werden.
Die einzige Möglichkeit, dies zu vermeiden, besteht darin, die Neuberechnung des Feldes zu vermeiden.
Eine Funktion, die eine Neuberechnung vermeiden kann, ist sub.
Das erste Feld konnte erfasst, dann mit sub von $ 0 entfernt und dann beide neu gedruckt werden.
Option 3
Selbst wenn wir den FS, den OFS ändern und / oder weitere Trennzeichen hinzufügen, funktioniert dies.
Wenn die Eingabedatei geändert wird in:
Und der Befehl ändert sich zu:
Die Ausgabe wird sein (wobei Trennzeichen erhalten bleiben):
Der Befehl kann auf mehrere Felder erweitert werden, jedoch nur mit modernen awks und mit aktivierter Option --re-interval. Dieser Befehl in der Originaldatei:
Wird dies ausgeben:
quelle
Wenn Sie offen für eine andere Perl-Lösung sind:
quelle
Es gibt auch eine Sed-Option ...
Erklärt ...
Ausführlicher erklärt ...
quelle
Noch ein anderer Weg ...
... verbindet die Felder 2 bis NF wieder mit dem FS und gibt eine Zeile pro Eingabezeile aus
Ich benutze dies mit git, um zu sehen, welche Dateien in meinem Arbeitsverzeichnis geändert wurden:
quelle
Eine andere und einfache Möglichkeit, den Befehl cat zu verwenden
quelle