2016-04-17 4 views
0

ersten 2lines meiner Daten zurückgegeben:Ich möchte nur die letzten 3 Zeichen einer Spalte auf die Originaldatei

"Rec_Open_Date","MSISDN","IMEI","Data_Volume_Bytes","Device_Manufacturer","Device_Model","Product_Description" 
"2015-10-06","123427","456060","137765","Samsung Korea","Samsung SM-G900I","$39 Plan" 

Ich möchte nur die letzten drei Zeichen der Spalte 2 und Spalte 3, I dont Spalte wollen Header betroffen. glücklich für eine Lösung, die column2 zuerst tun und dann Spalte 3 tun kann

Ich fummle mit sed und awk in der Minute, aber habe noch keine Freude.

das ist, was ich will:

"Rec_Open_Date","MSISDN","IMEI","Data_Volume_Bytes","Device_Manufacturer","Device_Model","Product_Description" 
"2015-10-06","427","060","137765","Samsung Korea","Samsung SM-G900I","$39 Plan" 

edit1 das gibt mir die letzten drei Ziffern (+ „), müssen nur diese zurück in die Datei orig schreiben

$ awk -F"," 'NR>1{ print $2}' head_test_real.csv | sed 's/.*\(....\)/\1/' 
427" 
592" 
007" 
592" 
409" 
742" 
387" 
731" 
556" 

edit2 das funktioniert, aber ich verliere die Anführungszeichen "123427" geht an 427, ich möchte die Anführungszeichen behalten
* NR> 1 funktioniert auf den Zeilen nach der ersten Zeile.

$ awk -F, 'NR>1{$2=substr($2,length($2)-3,3)}1' OFS=, head_test_real.csv 
"Rec_Open_Date","MSISDN","IMEI","Data_Volume_Bytes","Device_Manufacturer","Device_Model","Product_Description" 
"2015-10-06",427,"456060","137765","Samsung Korea","Samsung SM-G900I","$39 Plan" 

EDIT3 @ Mark tks fro richtige Antwort, und hier nur für meinen ref auf den Anführungszeichen.

$ ####csv.QUOTE_ALL 

$ cat out.csv 
"Rec_Open_Date","MSISDN","IMEI","Data_Volume_Bytes","Device_Manufacturer","Device_Model","Product_Description" 
"2015-10-06","427","060","137765","Samsung Korea","Samsung SM-G900I","$39 Plan" 



$ ####csv.QUOTE_MINIMAL 

$ cat out.csv 
Rec_Open_Date,MSISDN,IMEI,Data_Volume_Bytes,Device_Manufacturer,Device_Model,Product_Description 
2015-10-06,427,060,137765,Samsung Korea,Samsung SM-G900I,$39 Plan 

$ ###csv.QUOTE_NONNUMERIC 

$ cat out.csv 
"Rec_Open_Date","MSISDN","IMEI","Data_Volume_Bytes","Device_Manufacturer","Device_Model","Product_Description" 
"2015-10-06","427","060","137765","Samsung Korea","Samsung SM-G900I","$39 Plan" 



$ ###csv.QUOTE_NONE 

$ cat out.csv 
Rec_Open_Date,MSISDN,IMEI,Data_Volume_Bytes,Device_Manufacturer,Device_Model,Product_Description 
2015-10-06,427,060,137765,Samsung Korea,Samsung SM-G900I,$39 Plan 

Antwort

1
$ awk 'BEGIN{FS=OFS="\",\""} NR>1{for (i=2;i<=3;i++) $i=substr($i,length($i)-2)} 1' file 
"Rec_Open_Date","MSISDN","IMEI","Data_Volume_Bytes","Device_Manufacturer","Device_Model","Product_Description" 
"2015-10-06","427","060","137765","Samsung Korea","Samsung SM-G900I","$39 Plan" 

Wie bei jedem Befehl ist nur auf die Originaldatei zu schreiben zurück:

command file > tmp && mv tmp file 
+1

gute Antwort tks – HattrickNZ

+1

So hält das Muster: Ich posten eine Antwort behauptet 'awk' ist nicht ideal für das Problem, und @EdMorton posts eine elegante Antwort mit' awk'. Ich muss klar damit aufhören, das zu sagen. –

1

Perl zur Rettung!

perl -pe 's/",".*?(...",")/","$1/ if $. > 1' <input> output 
  • -p liest die Eingangs Zeile für Zeile und druckt das Ergebnis
  • s/regex/replacement/ eine Substitution ist
  • .*? alles passt (wie .*), aber die Fragezeichen macht es „sparsam“, dh es entspricht der kürzesten möglichen Zeichenfolge
  • (...",") erstellt eine Erfassungsgruppe, die drei Zeichen vor "," beginnt, kann als $1 bezeichnet werden .
  • $. ist die Zeilennummer, geschieht kein Ersatz auf der Linie 1.

Achten Sie darauf, die ersten beiden Spalten immer notiert sind und die zweite Spalte ist nie weniger als 3 Buchstaben.

die dritte Spalte ändern, können Sie die Regex

perl -pe 's/^("(?:.*?","){2}).*?(...",")/$1$2/ if $. > 1' 
#       ~ 

Ändern Sie die angezeigte Anzahl jede Spalte zu behandeln ändern können Sie möchten.

+0

, wie kann ich wissen Hut Spalte funktioniert es auf? – HattrickNZ

+0

@HattrickNZ: Sie zählen das '", "' in der Regex. Der erste entspricht der Grenze zwischen col1 und col2, der zweite col2-col3. Daher erfasst es den nachlaufenden Teil von col2. – choroba

+0

tks hat das, was ich versuchte herauszufinden, wie man es anpasst, so dass es auf Col3 funktioniert, einzeln oder gleichzeitig? Derzeit ändert es nur den Wert in Spalte2.
'$ perl -pe 's /",".*?(...",")/","$ 1/if $. > 1 ' HattrickNZ

2

Während awk scheint wie eine natürliche Passform für kommagetrennte Daten, ist es nicht gut mit der zitierten Felder-Version. Ich würde empfehlen, eine eigene CSV-Verarbeitungsbibliothek wie die Verwendung, die Schiffe mit Python (beide 2 und 3):

import csv 
with open('in.csv','r') as infile: 
    reader = csv.reader(infile) 
    with open('out.csv','w') as outfile: 
    writer = csv.writer(outfile,delimiter=',',quotechar='"',quoting=csv.QUOTE_ALL) 
    writer.writerow(next(reader)) 

    for row in reader: 
     row[1] = row[1][-3:] 
     row[2] = row[2][-3:] 
     writer.writerow(row) 

den obigen Code in eine Datei namens z Putfixcsv.py und machen Sie die Dateinamen mit dem, was Sie haben und wollen, dann führen Sie es einfach mit python fixcsv.py (oder python3 fixcsv.py).

Ich legte es auf alles in der Ausgabe (QUOTE_ALL) zitieren; Wenn Sie das nicht möchten, können Sie es auf QUOTE_MINIMAL, QUOTE_NONNUMERIC oder QUOTE_NONE setzen.

Die row Zuweisungen ersetzen die zweiten und dritten Felder (row[1] und row[2], da das erste Feld row[0] ist) mit den letzten drei Zeichen ([-3:]). Sie könnten es auch arithmetisch mit z.B. row[1] = int(row[1]) % 1000.

+1

++; funktioniert gut in Python 2.x; Was ist nötig, damit es in 3.x funktioniert? – mklement0

+0

gute Antwort tks – HattrickNZ

Verwandte Themen