Ändern der letzten Einträge in einer durch Kommas getrennten Liste

8

Ich habe eine riesige Textdatei, die so aussieht:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,3
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,8
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,12

Die gewünschte Ausgabe ist folgende:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

Ich habe andere relevante Beiträge hier und in anderen Communities ausprobiert, konnte aber nicht genau das bekommen, was ich will.

AKTUALISIEREN

Dies ist die Quer Frage (Ich wollte beide Unix / Perl Antworten und Batch / Powershell Lösungen für diese.) , Die interessanten Antworten hat.

M--
quelle

Antworten:

14

awk Ansatz mit Sprintf Funktion (um führende Nullen hinzuzufügen):

awk -F, -v OFS=',' '$8=sprintf("MI-%02d",$8);' file

Die Ausgabe:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

-F,- Komma ,als Feldtrennzeichen setzen

$8 - zeigt auf das achte Feld

%02d- Format, das das Funktionsargument als 2- stellige Zahl behandelt


Beachten Sie , dass das letzte Feld in einem Datensatz von angezeigt werden kann$NF.

NF ist eine vordefinierte Variable, deren Wert die Anzahl der Felder im aktuellen Datensatz ist

Also, $NFist das gleiche wie $8(für Ihre Eingabe)

awk -F, -v OFS=',' '$(NF)=sprintf("MI-%02d", $(NF))' file
RomanPerekhrest
quelle
1
Ein Wort der Warnung (in diesem Beispiel irrelevant, könnte aber in anderen Fällen zutreffen): Das Ändern eines Werts eines der Felder (hier: $ 8) "berechnet" die Felder der gesamten Zeile neu und hat Nebenwirkungen: Beispiel 1: Verliert mehrere Trennzeichen ': echo "1   2 3    4" | awk '{$2=$2;print $0}'ergibt: 1 2 3 4(nur noch 1 Leerzeichen (oder OFS) zwischen den Feldern). ex2) echo "1,,,2,3,,,,4" | awk -F',' '{$2=$2;print $0}'gibt: 1   2 3    4(Kommas wurden Leerzeichen). Es könnte andere Nebenwirkungen geben. Testen Sie einen anderen Ansatz (z. B. gsub für eine Kopiervariable von $ 0), wenn die Zuweisung eines Feldes nachteilige Nebenwirkungen hat.
Olivier Dulac
3

Sie können versuchen, Folgendes zu verwenden awk:

awk 'BEGIN { FS = OFS = "," } { $NF = sprintf("MI-%02d", $NF); } 1' file
Taliezin
quelle
2

Hier ist Perl-Lösung:

$ perl -F',' -lane '$last=$#F;$F[$last]=sprintf("MI-%02d",$F[$last]);print join ",", @F' input.txt                                       
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

Das -aFlag ermöglicht es uns, Eingaben als Array zu behandeln, basierend auf dem mit angegebenen Trennzeichen -F. Grundsätzlich ändern wir das letzte Element in diesem Array und erstellen es per joinBefehl neu.

Sergiy Kolodyazhnyy
quelle
Vielen Dank für Ihre Antwort. Es hilft, wenn jemand Perl braucht, sprintfist aber immer noch die Kernidee Ihrer Antwort. Nicht wie wenn es nicht richtig ist, nur nicht etwas anderes als akzeptierte Antwort anbieten. +1 sowieso.
M--
1
@Masoud gut, der Hauptgrund hierfür ist, dass sprintf()er normalerweise beim Schreiben einer Zeichenfolge eines bestimmten Formats in eine Variable verwendet wird, weshalb er in vielen anderen Sprachen verwendet wird. Ich kann es auch in Python schreiben - Python hat es nicht, sprintf()aber die Kernidee wird unabhängig davon dieselbe sein - formatierte Zeichenfolge in eine Variable schreiben. Alternativ können wir Array-Elemente direkt bearbeiten und diese einfach ausdrucken. Mit dieser Art von Fragen gibt es eine endliche Anzahl von Lösungen, im Grunde ist das, was ich zu sagen versuche
Sergiy Kolodyazhnyy
1

Mit Eingabedaten wie:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,3  
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,8  
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,14  
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,12  

in text.csv

den Code unten

awk -F"," '{ i = 0;
  MyOutLine = "";
  j = NF - 1;
  while ( i < j ) {
    i++;
    MyOutLine = MyOutLine""$i",";
  }
  i++;
  x = sprintf( "%.2i", $i );
  y = "MI-"x;
  MyOutLine = MyOutLine""y;
  print MyOutLine; }' ./text.csv  

erzeugt Ausgabe wie:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12
Norm
quelle
1

Tcl

Hier ist meine Lösung, die mit Tcl erstellt wurde, das aus der Datei input.csv liest und das Ergebnis in die Datei output.csv einfügt

set in [open input.csv]
set out [open output.csv w]

while {![eof $in]} {
   set line [gets $in]
   set last_comma_pos [string last , $line]
   puts $out [string range $line 0 $last_comma_pos][format MI-%02d [string range $line $last_comma_pos+1 end]]
}

close $in
close $out

Demonstration

Sergiol
quelle