Organiza las inputs como una spreadsheet (csv) usando awk

Tengo información para las inputs (N = 1000) guardadas en una computadora en un file de text delimitado / por input (cada input tiene un file de text). La información registrada en el mismo formatting que el siguiente:

============ NAME: Matty Nigan Age: 65 Sex: M Weight: XX TIME: 12:31:25 Home address: XXXXX Phone number: XXX XXX XXXX ============ 

Quiero recostackr y organizar todos los datos de estas inputs (N = 1000) de la siguiente manera:

 NAME AGE SEX Weight HOME Phone =========== Matty Nigan 65 M XX XX XX .......... .......... .......... .......... 

Intenté este código:

 #!/bin/bash source=path to the folder where the entries files are. for i in $(cat file.txt); do # file.txt is including all the delimited text files names awk ' /Name:/ {name=$2} /Age:/ {age=$2 } /Sex:/ {sex=$2} /Home: / {home=$3} /Phone:/ {phone=$3} BEGIN { FS=":"; print "name\t\tage\t\tsex\t\thome\t\tphone:\n---------"; } {print $2,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}END{ print "---------\nFile Complete" }' ' ${source}/${i}| sh > outdata.csv done 

Lamentablemente esto no funcionó! No sé lo que estoy haciendo mal. Cualquier ayuda es muy apreciada.

 awk ' BEGIN { fmt="%-15s%-10s%-10s%-10s%-10s%-10s\n" printf fmt,"Name","Age","Sex","Weight","Home","Phone" print "---------" } { v=$0 sub(/[^:]*: /, "", v) a[$1]=v } /Phone/ { printf fmt,a["NAME:"],a["Age:"],a["Sex:"],a["Weight:"],a["Home"],a["Phone"] delete a } END{ print "---------\nFile Complete" }' file* 

Usar tabs dobles entre columnas es problemático. Si hay, por ejemplo, nombres largos y nombres cortos, las columnas podrían confundir y terminar en los lugares incorrectos exactos. En lo anterior, formateé columnas con anchos dados. Es posible que necesite ajustar los anchos para get mejores resultados.

Tenga en count que FS=":" también es probable que cause problemas. Los campos pueden contener dos puntos y eso podría confundir el conteo. Esto puede evitarse rompiendo la información en el primer punto como las siguientes declaraciones. Estas declaraciones capturan toda la información del file en una matriz a :

 v=$0 sub(/[^:]*: /, "", v) a[$1]=v 

El primer campo es la key. Todo después del primer espacio de dos puntos es el valor.

Un solo command awk puede procesar muchos files. Como se indicó anteriormente, se procesan todos los files que coinciden con el file* glob file* . Reemplace esto con cualquier pegote que coincida con sus files de datos.

Lo anterior procesa a una persona a la vez. Esto significa que este código no requiere memory grande y, en consecuencia, es adecuado para grandes sets de datos.

Muestra de salida

 $ bash script.sh Name Age Sex Weight Home Phone --------- Matty Nigan 65 M XX XXXXX XXX XXX XXXX --------- File Complete 

Intenta usar un awk construido como se muestra a continuación. Construye una matriz con los detalles e imprime el lote al final.

 awk -F: ' /^NAME/{name[c]=$2} /^Age:/{age[c]=$2} /^Sex:/{sex[c]=$2} /^Weight:/{weight[c]=$2} /^Home address:/{home[c]=$2} /^Phone number:/{phone[c]=$2;c++} END { print "NAME AGE SEX Weight HOME Phone" print "===========" for(x in name) { printf "%-10s %3d %s %s %s %s\n", substr(name[x],2), age[x], sex[x], weight[x], home[x], phone[x] } }' 

Además, parece que la instrucción que comienza con "{print $ 2 …" se ejecutará para cada logging de input. Es mejor include la printing en las llaves después de / PHONE: / selector. Además, si lo hiciera, colocaría la parte BEGIN a la cabeza del progtwig, en lugar de incrustarla más abajo como está.

Como se señaló en el comentario anterior, la printing debe llamar nombre, edad, sexo, etc. en lugar de $ 2, $ 3, $ 4, etc.

Creo que / PHONE: / {phone = $ 3} te dará problemas. Como muestra la información de muestra, los tres grupos de dígitos del número de teléfono, separados por espacios, aparecerán como $ 3 $ 4 $ 5. Por lo tanto, para reunir todo el número de teléfono, / TELÉFONO: / {teléfono = $ 3 "-" $ 4 "-" $ 5} sería más apropiado.