Ich habe eine Datei mit vielen Zeilen. In jeder Zeile gibt es viele Spalten (Felder), die durch Leerzeichen getrennt sind. Die Anzahl der Spalten in jeder Zeile ist unterschiedlich. Ich möchte die ersten beiden Spalten entfernen. .wie man?
Sie können es mit cut
machen:
cut -d " " -f 3- input_filename > output_filename
Erklärung:
cut
: Rufen Sie den Ausschneidebefehl auf-d " "
: Verwenden Sie ein einzelnes Leerzeichen als Trennzeichen (cut
verwendet standardmäßig TAB).-f
: Geben Sie die zu speichernden Felder an3-
: alle Felder, die mit Feld 3 beginneninput_filename
: Verwenden Sie diese Datei als Eingabe> output_filename
: Schreibe die Ausgabe in diese Datei.Alternativ können Sie es auch mit awk
machen:
awk '{$1=""; $2=""; sub(" ", " "); print}' input_filename > output_filename
Erklärung:
awk
: Ruft den Befehl awk auf$1=""; $2="";
: Setzen Sie Feld 1 und 2 auf die leere Zeichenfolgesub(...);
: Bereinigen Sie die Ausgabefelder, da die Felder 1 und 2 weiterhin durch "" begrenzt werden.print
: druckt die modifizierte Zeileinput_filename > output_filename
: wie oben.Hier ist eine Möglichkeit, mit Awk relativ leicht zu verstehen:
awk '{print substr($0, index($0, $3))}'
Dies ist ein einfacher awk-Befehl ohne Muster. Die Aktion in {}
wird für jede Eingabezeile ausgeführt.
Die Aktion besteht darin, die Teilzeichenfolge einfach mit der Position des dritten Felds zu drucken.
$0
: die gesamte Eingabezeile$3
: 3. Feldindex(in, find)
: gibt die Position von find
in String in
zurücksubstr(string, start)
: Rückgabe eines Teilstrings ab Index start
Wenn Sie ein anderes Trennzeichen verwenden möchten, z. B. Komma, können Sie es mit der Option -F angeben:
awk -F"," '{print substr($0, index($0, $3))}'
Sie können dies auch für eine Teilmenge der Eingabezeilen ausführen, indem Sie vor der Aktion in {}
ein Muster angeben. Nur die Zeilen, die dem Muster entsprechen, lassen die Aktion ausführen.
awk 'pattern{print substr($0, index($0, $3))}'
Wo Muster sein kann, wie:
/abcdef/
: regulären Ausdruck verwenden, wird standardmäßig für $ 0 verwendet.$1 ~ /abcdef/
: bearbeitet ein bestimmtes Feld.$1 == blabla
: Stringvergleich verwendenNR > 1
: Datensatz-/Zeilennummer verwendenNF > 0
: Feld-/Spaltennummer verwendenVielen Dank, dass Sie die Frage gestellt haben. Ich möchte auch das Skript hinzufügen, das mir geholfen hat.
awk '{ $1=""; print $0 }' file
awk '{$1=$2="";$0=$0;$1=$1}1'
Eingang
a b c d
Ausgabe
c d
Es ist ziemlich einfach, dies nur mit Shell zu tun
while read A B C; do
echo "$C"
done < oldfile >newfile
Sie können sed
verwenden:
sed 's/^[^ ][^ ]* [^ ][^ ]* //'
Dies sucht nach Zeilen, die mit einem oder mehreren Nicht-Leerzeichen, einem Leerzeichen, einem weiteren Satz von Ein oder Mehrfach-Nicht-Leerzeichen und einem weiteren Leerzeichen beginnen, und löscht das übereinstimmende Material, dh die ersten beiden Felder. [^ ][^ ]*
ist geringfügig kürzer als die äquivalente, aber explizitere [^ ]\{1,\}
-Notation, und die zweite könnte Probleme mit GNU sed
haben (wenn Sie jedoch --posix
als Option verwenden, kann selbst GNU sed
es nicht schrauben oben). OTOH: Wenn die zu wiederholende Zeichenklasse komplexer war, gewinnt die nummerierte Notation an Bedeutung. Es lässt sich leicht erweitern, um 'Leerzeichen oder Tabulatoren' als Trennzeichen oder 'Mehrfach-Leerzeichen' oder 'Mehrfach-Leerzeichen oder Tabulatoren' zu behandeln. Es kann auch modifiziert werden, um optionale führende Leerzeichen (oder Tabulatoren) vor dem ersten Feld usw. zu behandeln.
Für awk
und cut
siehe Sampson-Chen 's answer . Es gibt andere Möglichkeiten, das Skript awk
zu schreiben, aber sie sind nicht wesentlich besser als die gegebene Antwort. Beachten Sie, dass Sie das Feldtrennzeichen in awk
möglicherweise explizit festlegen müssen (-F" "
), wenn Sie nicht möchten, dass Registerkarten als Trennzeichen behandelt werden oder wenn zwischen den Feldern mehrere Leerzeichen vorhanden sind. Der POSIX-Standard cut
unterstützt nicht mehrere Trennzeichen zwischen Feldern. GNU cut
verfügt über die nützliche, aber nicht standardmäßige -i
-Option, um mehrere Trennzeichen zwischen Feldern zu ermöglichen.
Sie können es auch in reiner Shell tun:
while read junk1 junk2 residue
do echo "$residue"
done < in-file > out-file
Perl:
Perl -lane 'print join(' ',@F[2..$#F])' File
awk:
awk '{$1=$2=""}1' File
Das könnte für Sie funktionieren (GNU sed):
sed -r 's/^([^ ]+ ){2}//' file
oder für Spalten, die durch ein oder mehrere Leerzeichen getrennt sind:
sed -r 's/^(\S+\s+){2}//' file
Durch die Verwendung von awk und basierend auf einigen der folgenden Optionen wird die Verwendung einer for-Schleife etwas flexibler. Manchmal möchte ich vielleicht die ersten 9 Spalten löschen (wenn ich zum Beispiel ein "ls -lrt" mache), also ändere ich die 2 gegen eine 9 und das wars:
awk '{ for(i=0;i++<2;){$i=""}; print $0 }' your_file.txt
Verwenden Sie kscript
kscript 'lines.split().select(-1,-2).print()' file