Ich habe eine riesige CSV-Datei mit 10 durch Kommas getrennten Feldern. Leider sind einige Zeilen fehlerhaft und enthalten nicht genau 10 Kommas (was einige Probleme verursacht, wenn ich die Datei in R einlesen möchte). Wie kann ich nur die Zeilen herausfiltern, die genau 10 Kommas enthalten?
9
sed
hier) nur bis zu einer Übereinstimmung mehr, als gesucht wird, obwohl diese Frage dies tut. Sie sollten dies nicht geschlossen haben.grep
Antwort gibt es keine akzeptable Antwort für beide Fragen ...Antworten:
Ein weiterer POSIX:
Wenn die Zeile 10 Kommas enthält, enthält diese Zeile 11 Felder. So einfach machen wir
awk
Gebrauch,
als Feldtrennzeichen. Wenn die Anzahl der Felder 11, die BedingungNF == 11
wahr ist ,awk
dann die Standardaktion ausführtprint $0
.quelle
-F
Legt das Feldtrennzeichen fest undNF
bezieht sich auf die Anzahl der Felder in einer bestimmten Zeile. Da{statement}
an die Bedingung kein Codeblock angehängt wirdNF == 11
, wird standardmäßig die Zeile gedruckt. (@cuonglm, zögern Sie nicht, diese Erklärung aufzunehmen, wenn Sie möchten.)awk -F , 'NF != 11' <file
-
oder benannt-
.Verwenden
egrep
(odergrep -E
in POSIX):Dies filtert alles heraus, was keine 10 Kommas enthält: Es entspricht den vollständigen Zeilen (
^
am Anfang und$
am Ende) und enthält genau zehn Wiederholungen ({10}
) der Sequenz "beliebig viele Zeichen außer ',', gefolgt von einem einzelnen ','". (([^,]*,)
), gefolgt von einer beliebigen Anzahl von Zeichen außer ',' ([^,]*
).Sie können den
-x
Parameter auch verwenden , um die Anker zu löschen:Dies ist jedoch weniger effizient als die Lösung von cuonglm
awk
. Letzteres ist auf meinem System für Zeilen mit etwa 10 Kommas normalerweise sechsmal schneller. Längere Leitungen führen zu enormen Verlangsamungen.quelle
Der einfachste
grep
Code, der funktioniert:Erläuterung:
-x
stellt sicher, dass das Muster mit der gesamten Linie übereinstimmt und nicht nur mit einem Teil davon. Dies ist wichtig, damit Sie keine Zeilen mit mehr als 10 Kommas abgleichen.-E
bedeutet "erweiterter regulärer Ausdruck", wodurch weniger Rückschläge in Ihrem regulären Ausdruck entstehen.Klammern werden zum Gruppieren verwendet, und das
{10}
bedeutet, dass in einer Reihe des Musters in den Klammern genau zehn Übereinstimmungen vorhanden sein müssen.[^,]
ist eine Zeichenklasse -[c-f]
würde beispielsweise mit jedem einzelnen Zeichen übereinstimmen, das ac
, ad
, ane
oder an istf
, und[^A-Z]
würde mit jedem einzelnen Zeichen übereinstimmen, das KEIN Großbuchstabe ist. Entspricht also[^,]
jedem einzelnen Zeichen außer einem Komma.Das
*
Nach der Zeichenklasse bedeutet "null oder mehr davon".Der Regex-Teil
([^,]*,)
bedeutet also "Beliebiges Zeichen außer einem Komma beliebig oft (einschließlich Null), gefolgt von einem Komma" und{10}
gibt 10 davon an. Dann[^,]*
, um den Rest der Nicht-Komma-Zeichen mit dem Ende der Zeile abzugleichen.quelle
Das verzweigt zuerst jede Zeile mit 11 oder mehr Kommas und druckt dann nur diejenigen aus, die mit 10 Kommas übereinstimmen.
Anscheinend habe ich das schon einmal beantwortet ... Hier ist ein Ich-Plagiat aus einer Frage, die nach genau 4 Vorkommen eines Musters sucht:
quelle
s/hello/world/2
mits//world/2
, GNU funktioniert sed. Mit zweised
aus dem Erbstück,/usr/5bin/posix/sed
Segfault erhöhen,/usr/5bin/sed
geht in Endlosschleife.sed
undawk
(in Kommentaren) - Ich mag diese Antwort und habe sie positiv bewertet, aber beachten Sie, dass die Übersetzung der akzeptiertenawk
Antwort lautet: "Zeilen mit 11 Feldern drucken " und die Übersetzung diesersed
Antwort lautet: " Versuchen Sie, das 11. Komma zu entfernen. Fahren Sie mit der nächsten Zeile fort, wenn Sie fehlschlagen. Versuchen Sie, das 10. Komma durch sich selbst zu ersetzen. Drucken Sie die Zeile, wenn Sie erfolgreich sind. " Dieawk
Antwort gibt dem Computer die Anweisungen so, wie Sie sie auf Englisch ausdrücken würden. (awk
ist gut für feldbasierte Daten.)Wirf ein paar kurze
python
:Dadurch wird jede Zeile gelesen und geprüft, ob die Anzahl der Kommas in der Zeile gleich 10
line.count(',') == 10
ist. Wenn dies der Fall ist, wird die Zeile gedruckt.quelle
Und hier ist ein Perl-Weg:
Die
-n
Ursachenperl
für das zeilenweise Lesen der Eingabedatei und das Ausführen des-e
in jeder Zeile angegebenen Skripts . Die-a
automatische Aufteilung wird aktiviert: Jede Eingabezeile wird nach dem durch-F
(hier ein Komma) angegebenen Wert aufgeteilt und als Array gespeichert@F
.Der
$#F
(oder allgemeiner$#array
) ist der höchste Index des Arrays@F
. Da Arrays bei beginnen0
, hat eine Zeile mit 11 Feldern ein@F
von10
. Das Skript druckt daher die Zeile, wenn es genau 11 Felder enthält.quelle
print if @F==11
als Array in einem skalaren Kontext die Anzahl der Elemente zurückgeben.Wenn Felder Kommas oder Zeilenumbrüche enthalten können, muss Ihr Code csv verstehen . Beispiel (mit drei Spalten):
Ich nehme an, dass die meisten Lösungen bisher die zweite und vierte Zeile verwerfen würden.
quelle