Cambiar las últimas entradas en una lista delimitada por comas

8

Tengo un archivo de texto enorme que se ve así:

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

La salida deseada es esta:

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

He probado otras publicaciones relevantes aquí y en otras comunidades, pero no pude obtener exactamente lo que quiero.

ACTUALIZAR

Esta es la pregunta cruzada (quería respuestas Unix / perl y soluciones batch / powershell para esto) que tiene respuestas interesantes.

METRO--
fuente

Respuestas:

14

enfoque awk confunción sprintf (para agregar ceros a la izquierda):

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

La salida:

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,- Establecer coma ,como separador de campo

$8 - apunta al octavo campo

%02d- formato que trata el argumento de la función como un número de 2 dígitos


Tenga en cuenta que el último campo en un registro puede ser presentado por$NF.

NF es una variable predefinida cuyo valor es el número de campos en el registro actual

Entonces, $NFes lo mismo que $8(para su entrada)

awk -F, -v OFS=',' '$(NF)=sprintf("MI-%02d", $(NF))' file
RomanPerekhrest
fuente
1
Una palabra de advertencia (irrelevante en este ejemplo, pero podría aplicarse en otros casos): cambiar el valor de uno de los campos (aquí: $ 8) "recalcula" los campos de toda la línea y tiene efectos secundarios: ex1: pierde los separadores múltiples ': echo "1   2 3    4" | awk '{$2=$2;print $0}'da: 1 2 3 4(solo queda 1 espacio (u OFS) entre campos). ex2) echo "1,,,2,3,,,,4" | awk -F',' '{$2=$2;print $0}'da: 1   2 3    4(las comas se convirtieron en espacios). Podría haber otros efectos secundarios. Pruebe y adopte otro enfoque (gsub en una variable de copia de $ 0, por ejemplo) si asignar un campo tiene efectos secundarios perjudiciales.
Olivier Dulac
3

Puedes intentar usar awk:

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

Aquí está la solución perl:

$ 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

El -aindicador nos permite tratar la entrada como una matriz, basada en el separador especificado con -F. Básicamente, modificamos el último elemento de esa matriz y lo reconstruimos mediante un joincomando.

Sergiy Kolodyazhnyy
fuente
Gracias por su respuesta. Ayuda si alguien necesita Perl, pero sigue sprintfsiendo la idea central de su respuesta. No es como si no fuera correcto, simplemente no ofrece algo diferente a la respuesta aceptada. +1 de todos modos.
M--
1
@Masoud, la razón principal aquí es porque sprintf()se usa típicamente cuando se escribe una cadena de formato específico en una variable, razón por la cual se usa en muchos otros idiomas. También puedo escribirlo en Python: Python no tiene, sprintf()pero la idea central será la misma independientemente: escribir una cadena formateada en una variable. Alternativamente, podemos operar en elementos de matriz directamente e imprimirlos. Con este tipo de preguntas hay una cantidad finita de soluciones, básicamente es lo que estoy tratando de decir
Sergiy Kolodyazhnyy
1

Con datos de entrada como:

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  

en text.csv

el siguiente código

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  

produce resultados como:

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
Norma
fuente
1

Tcl

Aquí está mi solución, hecha usando Tcl que lee del archivo input.csv y coloca el resultado en el archivo output.csv

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

demostración

sergiol
fuente