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
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