Entfernen Sie nur die Kommas in doppelten Anführungszeichen

10

In einer Textdatei möchte ich ,(Kommas) und auch "(Anführungszeichen) entfernen ( nur wenn die doppelten Anführungszeichen durch Kommas getrennte Zahlen enthalten).

56,72,"12,34,54",x,y,"foo,a,b,bar"

Erwartete Ausgabe

56,72,123454,x,y,"foo,a,b,bar"

Hinweis: Ich zeige die obige Zeile nur als Beispiel. Meine Textdatei enthält viele Zeilen wie oben und die durch Kommas getrennten Zahlen in doppelten Anführungszeichen sollten variieren. Das ist,

56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"

Erwartete Ausgabe:

56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

Es gibt eine nReihe von Zahlen in doppelten Anführungszeichen, die durch Kommas getrennt sind. Lassen Sie auch die doppelten Anführungszeichen, die Zeichen enthalten, so wie sie sind.

Ich liebe sedTextverarbeitungswerkzeug. Ich freue mich, wenn Sie eine sedLösung dafür veröffentlichen.

Avinash Raj
quelle
Von 56,72,"12,34,54",x,y,"foo,a,b,bar"zu 56,72,123454,x,y,"a,b", foound barheißt verschwinden. Ist es Ihre gewünschte Ausgabe?
Cuonglm
Das von Ihnen verwendete Beispiel ist etwas verwirrend, da einige Elemente (wie foound bar) zusammen mit den Kommas entfernt werden. Darüber hinaus verschwinden einige der Zitate dort, wo andere verbleiben. Ganz zu schweigen davon, dass die Kommas zwischen aund auch bbleiben. Gibt es ein Muster für diese?
HalosGhost
sorry Freunde bearbeitet.
Avinash Raj
Ihre Änderungen haben Ihr Beispiel nicht wirklich klargestellt. Bitte beachten Sie meinen letzten Kommentar .
HalosGhost
Entfernen Sie alle Kommas in doppelten Anführungszeichen und auch die Anführungszeichen nur, wenn die Anführungszeichen Zahlen enthalten.
Avinash Raj

Antworten:

7

Dies (von hier aus angepasst ) sollte das tun, was Sie brauchen, obwohl @ Ricis Perl viel einfacher ist:

$ sed -r ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;ta; s/""/","/g; 
          s/"([0-9]*)",?/\1,/g ' file
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454,
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

Erläuterung

  • :a: Definieren Sie eine Bezeichnung mit dem Namen a.
  • s/(("[0-9,]*",?)*"[0-9,]*),/\1/ : Dieser muss abgebaut werden
    • Zuallererst wird und wird mit diesem Konstrukt : (foo(bar)), sein .\1foobar\2bar
    • "[0-9,]*",?: 0 oder mehr von 0-9oder ,, gefolgt von 0 oder 1 ,.
    • ("[0-9,]*",?)* : 0 oder mehr der oben genannten übereinstimmen.
    • "[0-9,]*: Match 0 oder mehr von 0-9oder ,die kommen direkt nach a"
  • ta;: Gehen Sie zurück zum Label aund führen Sie es erneut aus, wenn die Ersetzung erfolgreich war.
  • s/""/","/g;: Nachbearbeitung. Ersetzen ""durch ",".
  • s/"([0-9]*)",?/\1,/g : Entfernen Sie alle Anführungszeichen um Zahlen.

Dies könnte mit einem anderen Beispiel leichter zu verstehen sein:

$ echo '"1,2,3,4"' | sed -nr ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;p;ta;'
"1,2,34"
"1,234"
"1234"
"1234"

Während Sie also eine Zahl finden, die direkt nach einem Anführungszeichen steht, gefolgt von einem Komma und einer anderen Zahl, verbinden Sie die beiden Zahlen miteinander und wiederholen Sie den Vorgang, bis dies nicht mehr möglich ist.

An dieser Stelle info sedhalte ich es für nützlich, ein Zitat aus dem Abschnitt zu erwähnen , der erweiterte Funktionen wie die oben verwendete Bezeichnung beschreibt (danke, dass Sie herausgefunden haben, ob @Braiam):

In den meisten Fällen bedeutet die Verwendung dieser Befehle, dass Sie wahrscheinlich besser in etwas wie "awk" oder Perl programmieren sollten.

terdon
quelle
10

Wenn Perl in Ordnung ist, gibt es hier eine kurze (und wahrscheinlich schnelle, wenn nicht unbedingt einfache :)) Möglichkeit, dies zu tun:

perl -pe 's:"(\d[\d,]+)":$1=~y/,//dr:eg' file

Das eFlag für den s:::Operator (dies ist nur eine andere Schreibweise s///) bewirkt, dass die Ersetzung als Ausdruck behandelt wird, der jedes Mal ausgewertet wird. Dieser Ausdruck übernimmt die $1Erfassung aus dem regulären Ausdruck (in dem bereits die Anführungszeichen fehlen) und übersetzt sie ( y///was auch als geschrieben werden kann tr///), indem /dalle Kommas gelöscht ( ) werden. Das rFlag to yist erforderlich, um den Wert als übersetzte Zeichenfolge anstelle der Anzahl der Übersetzungen zu erhalten.

Für diejenigen, die sich irgendwie von Perl besudelt fühlen, ist hier das Python-Äquivalent. Python ist wirklich kein Shell-Einzeiler-Tool, aber manchmal kann es zur Zusammenarbeit überredet werden. Folgendes kann als eine Zeile geschrieben werden (im Gegensatz zu forSchleifen, die nicht sein können), aber das horizontale Scrollen macht es (noch mehr) unlesbar:

python -c '
import re;
import sys;
r=re.compile("\"(\d+(,\d+)*)\"");
all(not sys.stdout.write(r.sub(lambda m:m.group(1).replace(",",""),l))
    for l in sys.stdin)
' < file
Rici
quelle
@rici: Gut! Und verwenden Sie, y///anstatt tr///uns einen weiteren Charakter zu speichern.
Cuonglm
6

Für CSV-Daten würde ich eine Sprache mit einem echten CSV-Parser verwenden. Zum Beispiel mit Ruby:

ruby -rcsv -pe '
  row = CSV::parse_line($_).map {|e| e.delete!(",") if e =~ /^[\d,]+$/; e} 
  $_  = CSV::generate_line(row)
' <<END
56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"
END
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"
Glenn Jackman
quelle
0

Blockquote

Hallo, hier ist der Python- Code zum Ersetzen von Kommas in doppelten Anführungszeichen. Kommas werden durch Pipe-Zeichen (|) ersetzt

Dieser Python-Code ersetzt Kommas in doppelten Anführungszeichen

zB: x, y, z, 1,2, "r, e, t, y", h, 8,5,6

wenn durch Rohr x, y, z, 1,2, "r | e | t | y", h, 8,5,6 ersetzen

wenn durch null x, y, z, 1,2, "rety", h, 8,5,6 ersetzen

writingFile = open('FileToWrite', 'w')
with open('FileToRead') as f:

    while True:

        c = f.read(1)
        if not c:
            print ("End of file")
            break
        print ("Read a character:", c)


        if c=='"':
            writingFile.write(c) 
            c = f.read(1)
            while c != '"':
                if c== ',':
                    c= '|'
                writingFile.write(c)
                c = f.read(1)


        writingFile.write(c)


writingFile.close()
Vijay Kumar Akarapu
quelle
wenig Erklärung nötig.
Mischling
Dieser Python-Code wird verwendet, um Dinge in doppelten Anführungszeichen zu ersetzen
Vijay Kumar Akarapu