2010-02-05 16 views
8

esta es mi situación: tenía un gran archivo de texto del que quería extraer cierta información. Usé sed para extraer toda la información relevante basada en expresiones regulares, pero cada "pieza" de información que extraje está en una línea separada, me gustaría que cada "registro" esté en su propia línea para que pueda ser importado fácilmente a un DB.
He aquí una muestra de mis datos en este momento:Usando awk (o sed) para eliminar nuevas líneas basadas en el primer carácter de la siguiente línea

92831.499.000
, 0644321
79217.999.000
, 5.417.178
, PK91622
, PK90755

Idealmente, Me gustaría que este resultado se vea así:

92831,499,000 , 0.644.321
79217.999.000 , 5.417.178 , PK91622
79217.999.000 , 5.417.178 , PK90755

Esto puede ser más difícil de hacer, por lo que se conformaría para que la salida de ese último "registro" aparezca solo una vez con el "PK ..." adicional para ser el 4 ° "campo" de esa línea.
Al final, la manera más simple que se me ocurre es si la línea comienza con una coma (^,) la nueva línea antes de que se elimine ... No estoy muy familiarizado con awk, así que si pudiera dar ¡un comienzo en esto realmente sería apreciado! ¡Gracias!

Respuesta

2

Bueno, supongo que debería haber mirado más de cerca el uso de los registros en awk cuando estaba tratando de resolver esto anoche ... 10 minutos después de mirarlos lo conseguí trabajando. Para cualquier persona interesada, así es como hice esto: En mi script sed original puse una línea nueva adicional delante del comienzo de cada registro, así que ahora hay una línea en blanco separando cada una. Luego uso el siguiente comando awk:

awk 'BEGIN {RS = ""; FS = "\ n"}
{
si (NF> = 3)
for (i = 3; i < = NF; i ++)
de impresión $ 1, $ 2, $ i
}'

y funciona como un amuleto de salida exactamente como yo quería!

+0

+1 programa a veces simple> regex – gbarry

1
sedsed -d -n ':t;/^,/!x;H;n;/^,/{x;$!bt;x;H};x;s/\n//g;p;${x;/^,/!p}' filename 
1

Sin caja especial de campo 3, fácil.

awk ' 
    !/^,/ { if (NR > 1) print x ; x = $0 } 
    /^,/ { x = x OFS $0 } 
    END  { if (NR) print x } 
' 

Con, más complejo, pero no demasiado difícil.

awk ' 
    !/^,/ { if (n && n < 3) print x ; x = $0 ; n = 1 } 
    /^,/ { if (++n > 2) { print x, $0 } else { x = x OFS $0 } } 
    END  { if (n && n < 3) print x } 
' 
5
 
$ perl -0pe 's/\n,/,/g' < test.dat 
92831,499,000,0644321 
79217,999,000,5417178,PK91622,PK90755 

Traducción: Leer a granel sin separación de la línea, de extraerse de cada coma después de un salto de línea con sólo una coma.

¡El código más corto aquí!

1

Esto podría funcionar para usted:

# sed ':a;N;s/\n,/,/;ta;P;D' test.dat | sed 's/,/\n/5;s/\(.*,\).*\n/&\1/' 
92831,499,000,0644321 
79217,999,000,5417178,PK91622 
79217,999,000,5417178,PK90755 

Explicación:

Esto viene en dos partes:

añada la siguiente línea y luego, si la línea añadida comienza con un ,, elimine el incrusta la nueva línea \n y comienza de nuevo. Si no imprime hasta la nueva línea y luego elimínela hasta la nueva línea. Repetir.

Reemplace el 5th , con una nueva línea. Luego inserte los primeros cuatro campos entre la línea nueva incrustada y el sexto campo.

Cuestiones relacionadas