So löschen Sie die letzte Spalte einer Datei unter Linux

Ich möchte die letzte Spalte einer txt-Datei löschen, ohne die Spaltennummer zu kennen ist. Wie kann ich das machen?

Beispiel:

Eingabe:

1223 1234 1323 ... 2222 123 1233 1234 1233 ... 3444 125 0000 5553 3455 ... 2334 222 

Und ich möchte, dass meine Ausgabe erfolgt :

1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

Kommentare

  • Es gibt viele Möglichkeiten, dies zu tun. Bitte fügen Sie ein Beispiel hinzu und Ihre erwartete Ausgabe davon.
  • @heemayl ok, ich habe
  • Danke. Sind die Spalten durch Spalten oder Leerzeichen getrennt?
  • @heemayl Leerzeichen ist ein Trennzeichen
  • cut klingt wie das Werkzeug für den Job.

Antwort

Mit awk:

awk "NF{NF-=1};1" <in >out 

oder:

awk "NF{NF--};1" <in >out 

oder:

awk "NF{--NF};1" <in >out 

Obwohl dies wie Voodoo aussieht, funktioniert es. Jeder dieser awk-Befehle besteht aus drei Teilen.

Der erste ist NF, was eine Voraussetzung für den zweiten Teil ist. NF ist eine Variable, die die Anzahl der Felder in einer Zeile enthält. In AWK sind Dinge wahr, wenn sie „nicht 0 oder eine leere Zeichenfolge "" sind. Daher der zweite Teil (wobei NF dekrementiert wird) tritt nur auf, wenn NF nicht 0 ist.

Der zweite Teil (entweder NF-=1 oder --NF) subtrahiert nur eine von der Variablen NF. Dies verhindert, dass das letzte Feld gedruckt wird, denn wann Wenn Sie ein Feld ändern (in diesem Fall das letzte Feld entfernen), awk $0 neu konstruieren, alle standardmäßig durch Leerzeichen getrennten Felder verketten $0 enthielt nicht mehr das letzte Feld.

Der letzte Teil ist 1. Es ist nicht magisch, es wird nur als Ausdruck verwendet, der true bedeutet. Wenn ein awk -Ausdruck ohne zugehörige Aktion als wahr ausgewertet wird, lautet die awk Standardaktion print $0 .

Kommentare

  • @JJoao: Ah, danke, ich habe -- vergessen. Ein Hinweis, derzeit benötigen Sie ;1 für POSIX-kompatibel.
  • Mein anfänglicher Instinkt wäre die Verwendung einer for-Schleife, aber dies ist viel prägnanter und cleverer.
  • ‚ Es ist erwähnenswert, dass Sie iv id, wenn Sie ‚ ein nicht standardmäßiges Trennzeichen verwenden = „f70267324d“>

muss einige Änderungen vornehmen. Angenommen,,ist Ihr Trennzeichen:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out

  • Der Effekt der Dekrementierung von NF ist ein undefiniertes Verhalten von POSIX – Sie erhalten Unterschiedliche Ausgabe, je nachdem, welche awk Sie ‚ ausführen. Einige awks entfernen das letzte Feld wie gewünscht, andere tun überhaupt nichts und andere melden möglicherweise einen Syntaxfehler oder etwas anderes.
  • Antwort

    Verwenden von grep mit PCRE:

    $ grep -Po ".*(?=\s+[^\s]+$)" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

    Verwenden von GNU sed:

    $ sed -r "s/(.*)\s+[^\s]+$/\1/" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

    Kommentare

    • @ramin Sicher. Könnten Sie es bitte als eine neue Frage stellen (so funktioniert diese Seite) 🙂
    • @ramin Gibt es Ihnen eine Zeitbeschränkung oder eine Warnung?
    • es heißt, dass dies nicht in Frage kommt!
    • @ramin Ok..Lass mich einen Administrator kontaktieren, vielleicht können sie dir dabei helfen .. Übrigens, haben Sie eine alte Qualitätssicherung bezüglich Ihrer Frage überprüft? Es besteht die Möglichkeit, dass die Frage bereits gestellt und beantwortet wird.
    • Stellen Sie ‚ keine grundlegenden Fragen wie “ Wie kann ich einen Dateinamen unter Linux umbenennen? „. Verwenden Sie Google.

    Antwort

    Verwenden von Perl:

    perl -lane "$,=" ";pop(@F);print(@F)" in 

    Verwenden von rev + cut:

    rev in | cut -d " " -f 2- | rev 

    Antwort

    Verwenden von GNU sed:

    sed -r "s/\s+\S+$//" input.txt 

    Im Allgemeinen diese funktioniert mit dem BSD sed in OSX sowie mit GNU sed:

    sed "s/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//" input.txt 

    Antwort

    Wenn das Trennzeichen immer ein einzelnes Zeichen ist (zwei oder mehr aufeinanderfolgende Trennzeichen kennzeichnen leere Felder), können Sie head nur die erste Zeile Ihrer Eingabedatei verwenden und die Trennzeichen zählen ( n Trennzeichen bedeuten, dass die Anzahl der Felder n+1 ist.) Verwenden Sie dann cut, um aus dem 1 st Feld bis zum n -ten Feld (vorletztes Feld), z mit tabulatorgetrennten Eingaben:

    n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l) cut -f1-$n infile > outfile 

    oder z.mit einer csv -Datei:

    n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l) cut -d, -f1-$n infile > outfile 

    Ich werde später einige Benchmarks ausführen, wenn ich Zeit habe, aber mit großem Input denke ich das Die Lösung sollte schneller sein als andere Lösungen, die Regex verwenden, da diese in der ersten Zeile nur eine minimale Verarbeitung durchführt, um die Anzahl der Felder zu ermitteln, und dann cut verwendet, das für diesen Job optimiert ist.

    Antwort

    Portabel können Sie eine der folgenden Optionen verwenden:

    sed "s/[[:space:]]*[^[:space:]]*$//" file awk "{sub(/[[:space:]]*[^[:space:]]*$/,"")}1" file 

    Antwort

    Verwenden von vim:

    Öffnen Sie die Datei in vim

    vim <filename> 

    Gehen Sie zur ersten Zeile, nur für den Fall, dass sich der Cursor an einer anderen Stelle befindet.

    gg 

    Erstellen Sie ein Makro mit dem Namen „q“ qq, das zum Ende der aktuellen Zeile $ und dann zum letzten Leerzeichen F (Großbuchstabe F, gefolgt von Literal SPACE) und dann von der aktuellen Position bis zum Ende der Zeile D Gehen Sie zur nächsten Zeile j und beenden Sie die Makroaufzeichnung mit q.

    qq$F Djq 

    Jetzt können wir unser Makro mit @q für jede Zeile wiederholen.
    Wir können auch @@ um das letzte Makro zu wiederholen oder noch einfacher:

    99@q 

    um das Makro 99 Mal zu wiederholen.
    Hinweis: Die Zahl darf nicht genau mit den Zeilen übereinstimmen.

    Antwort

    Für Personen mit einem ähnlichen Problem, aber mit unterschiedlichen Feldtrennzeichen ist dies awk behält das Feldtrennzeichen korrekt bei:

    $ cat file foo.bar.baz baz.bar.foo $ awk -F"." "sub(FS $NF,x)" file foo.bar baz.bar 

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.