Ich habe eine sehr große CSV-Datei. Wie würden Sie das allerletzte ,
mit sed (oder ähnlichem) entfernen ?
...
[11911,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11912,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11913,0,"BUILDER","2014-10-15","BUILDER",0,0],
]
Gewünschte Ausgabe
...
[11911,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11912,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11913,0,"BUILDER","2014-10-15","BUILDER",0,0]
]
Der folgende sed-Befehl löscht das letzte Vorkommen pro Zeile, aber ich möchte pro Datei.
sed -e 's/,$//' foo.csv
Das funktioniert auch nicht
sed '$s/,//' foo.csv
Antworten:
Verwenden
awk
Wenn das Komma immer am Ende der vorletzten Zeile steht:
Verwenden von
awk
undbash
Verwenden
sed
Versuchen Sie für OSX und andere BSD-Plattformen Folgendes:
Verwenden
bash
quelle
sed: 1: "x;${s/,$//;p;x}; 2,$ p": extra characters at the end of x command
sed
und es ist oft auf subtile Weise anders. Ich habe keinen Zugriff auf OSX, um dies zu testen, aber bitte versuchen Sie essed -n -e x -e '${s/,$//;p;x;}' -e '2,$ p' input
Probieren Sie einfach den folgenden Perl-Einzeilenbefehl aus.
Erläuterung:
,
Entspricht einem Komma.(?!.*,)
Negative Vorausschau behauptet, dass es nach diesem übereinstimmenden Komma kein Komma mehr geben würde. Es würde also zum letzten Komma passen.s
Und dass
Wichtigste ist der DOTALL-Modifikator, mit dem Punkt auch für Zeilenumbrüche geeignet ist.quelle
perl -0777 -pi -e 's/(.*),(.*?)/\1\2/s'
. Dies funktioniert, weil der erste.*
gierig ist, während der zweite nicht ist.Das sollte nur das letzte Vorkommen von a
,
in einer Eingabedatei entfernen - und es werden weiterhin diejenigen gedruckt, in denen a,
nicht vorkommt. Grundsätzlich werden Zeilenfolgen gepuffert, die kein Komma enthalten.Wenn es auf ein Komma stößt, tauscht es den aktuellen Zeilenpuffer mit dem Haltepuffer aus und gibt auf diese Weise gleichzeitig alle Zeilen aus, die seit dem letzten Komma aufgetreten sind, und gibt seinen Haltepuffer frei.
Ich habe gerade meine Verlaufsdatei durchsucht und Folgendes gefunden:
Es ist eigentlich ziemlich gut. Ja, es verwendet
eval
, aber es übergibt ihm nie etwas anderes als einen numerischen Verweis auf seine Argumente. Es werden beliebigesed
Skripte für die Behandlung eines letzten Matches erstellt. Ich werde Ihnen zeigen:Das druckt folgendes zu stderr. Dies ist eine Kopie der
lmatch
Eingabe von:Die
eval
ed-Subshell der Funktion durchläuft alle Argumente einmal. Wenn es über sie läuft, iteriert es einen Zähler entsprechend dem Kontext für jeden Schalter und überspringt so viele Argumente für die nächste Iteration. Von da an macht es eines von ein paar Dingen pro Argument:$a
zu$o
.$a
wird basierend auf dem Wert zugewiesen, der$i
für jedes verarbeitete Argument um die Anzahl der Argumente erhöht wird.$a
erhält einen der beiden folgenden Werte:a=$((i+=1))
- Dies wird zugewiesen, wenn entweder an eine Short-Option kein Argument angehängt ist oder wenn die Option eine Long-Option war.a=$i#-?
- dies wird zugewiesen , wenn die Option ein kurzer und nicht hat seine arg angehängt.a=\${$a}${1:+$d\${$(($1))\}}
- Unabhängig von der anfänglichen Zuweisung wird$a
der Wert immer in geschweifte Klammern gesetzt und in einigen-s
Fällen$i
um eins erhöht und zusätzlich ein abgegrenztes Feld angehängt.Das Ergebnis ist, dass
eval
niemals ein String übergeben wird, der Unbekanntes enthält. Jedes der Befehlszeilenargumente wird durch seine numerische Argumentnummer bezeichnet - selbst das Trennzeichen, das aus dem ersten Zeichen des ersten Arguments extrahiert wird und das einzige Mal ist, dass Sie ein beliebiges Zeichen ohne Maskierung verwenden sollten. Grundsätzlich ist die Funktion ein Makrogenerator - sie interpretiert die Werte der Argumente niemals auf besondere Weise, dased
dies beim Parsen des Skripts problemlos möglich (und selbstverständlich auch möglich) ist . Stattdessen ordnet es seine Argumente nur sinnvoll in einem funktionsfähigen Skript an.Hier ist eine Debug-Ausgabe der Funktion bei der Arbeit:
Auf diese Weise
lmatch
können Sie ganz einfach reguläre Ausdrücke auf Daten anwenden, die auf die letzte Übereinstimmung in einer Datei folgen. Das Ergebnis des Befehls, den ich oben ausgeführt habe, ist:... die angesichts der Teilmenge der Dateieingabe, die dem letzten Mal
/^.0/
folgt, übereinstimmt, die folgenden Ersetzungen anwendet:sdd&&&&d
- ersetzt$match
sich 4 mal.sd'dsqd4
- das vierte einfache Anführungszeichen nach dem Zeilenanfang seit dem letzten Spiel.sd"d\dqd2
- ebenso, aber für doppelte Anführungszeichen und global.So zeigen Sie, wie Sie
lmatch
das letzte Komma in einer Datei entfernen können:AUSGABE:
quelle
-m
Option gelöscht und sie als obligatorisch erklärt, zu mehreren Argumenten für re und repl für gewechselt-s
und auch die ordnungsgemäße Behandlung von Begrenzern implementiert. Ich denke, es ist kugelsicher. Ich habe erfolgreich ein Leerzeichen und ein einfaches Anführungszeichen als Trennzeichen verwendet.Wenn das Komma möglicherweise nicht in der vorletzten Zeile steht
Verwenden
awk
undtac
:Der
awk
Befehl ist einfach, um die Substitution durchzuführen, wenn das Muster zum ersten Mal angezeigt wird.tac
Kehrt die Reihenfolge der Zeilen in der Datei um, sodass derawk
Befehl das letzte Komma entfernt.Mir wurde das gesagt
kann effizienter sein.
quelle
Wenn Sie verwenden können
tac
:quelle
Siehe /programming/12390134/remove-comma-from-last-line
Das hat bei mir geklappt:
Am besten entferne ich die letzte Zeile und füge nach dem Entfernen des Kommas das Zeichen] erneut hinzu
quelle
Versuchen Sie es mit unten
vi
:Erläuterung:
$-1
Wählen Sie die vorletzte Zeiles
ersetzen\(,\)\(\_s*]\)
Suchen Sie ein Komma, gefolgt von]
und getrennt durch Leerzeichen oder Zeilenumbrüche\2
Ersetzen durch\(\_s*]\)
zB Leerzeichen oder Zeilenvorschub gefolgt von]
quelle
Versuchen Sie es mit dem folgenden
sed
Befehl.quelle