Domanda

Ho alcuni file di dati da un sistema legacy che vorrei elaborare con Awk. Ogni file è composto da un elenco di record. Ci sono diversi tipi di record diversi e ogni tipo di record ha un diverso insieme di campi a larghezza fissa (non c'è campo carattere separatore). I primi due caratteri del record indicano il tipo, da questo poi si sa che i campi dovrebbero seguire. Un file potrebbe essere simile a questo:

AAField1Field2LongerField3
BBField4Field5Field6VeryVeryLongField7Field8
CCField99

Utilizzando Gawk posso impostare il FIELDWIDTHS , ma che vale per l'intero file (a meno che non mi manca qualche modo di impostare questo su un record per record base), o posso impostare FS "" e elaborare il file di un carattere alla volta, ma questo è un po ' ingombrante.

C'è un buon modo per estrarre i campi da un file utilizzando Awk?

Modifica : Sì, potrebbero usare Perl (o qualcos'altro). Sono ancora interessati a sapere se c'è un modo sensato di farlo con Awk però.

È stato utile?

Soluzione

Speriamo che questo vi condurrà nella giusta direzione. Supponendo che i record multilinea sono garantiti per essere terminato da un tipo di riga 'CC' è possibile pre-processo il file di testo utilizzando semplice logica if-then. Ho presunto si richiede fields1,5 e 7 su una riga e uno script di esempio awk sarebbe.

BEGIN {
        field1=""
        field5=""
        field7=""
}
{
    record_type = substr($0,1,2)
    if (record_type == "AA")
    {
        field1=substr($0,3,6)
    }
    else if (record_type == "BB")
    {
        field5=substr($0,9,6)
        field7=substr($0,21,18)
    }
    else if (record_type == "CC")
    {
        print field1"|"field5"|"field7
    }
}

Crea un file di script awk chiamato program.awk e pop che il codice in esso. Eseguire lo script utilizzando:

awk -f program.awk < my_multi_line_file.txt 

Altri suggerimenti

È forse possibile utilizzare due passaggi:

1step.awk

/^AA/{printf "2 6 6 12"    }
/^BB/{printf "2 6 6 6 18 6"}
/^CC/{printf "2 8"         }
{printf "\n%s\n", $0}

2step.awk

NR%2 == 1 {FIELDWIDTHS=$0}
NR%2 == 0 {print $2}

E poi

awk -f 1step.awk sample  | awk -f 2step.awk

Probabilmente è necessario sopprimere (o almeno ignorare) awk incorporato nel codice di separazione di campo, e utilizzare un programma lungo le linee di:

awk '/^AA/ { manually process record AA out of $0 }
     /^BB/ { manually process record BB out of $0 }
     /^CC/ { manually process record CC out of $0 }' file ...

L'elaborazione manuale sarà un po 'laborioso - Suppongo che è necessario utilizzare la funzione substr per estrarre ogni campo in base alla posizione, quindi quello che ho come una riga per tipo di record sarà più come una linea per ogni campo in ogni tipo di record, più il follow-on stampa.

Io credo che si potrebbe essere meglio con Perl e la sua caratteristica unpack, ma awk in grado di gestire anche io, anche se verbosely.

Potreste usare Perl e quindi selezionare un modello di decompressione basata sui primi due caratteri della linea?

utilizzare meglio alcuni linguaggio di scripting completamente descritto come Perl o Ruby.

Che dire 2 script? Per esempio. Primo script inserisce separatori di campo in base ai primi caratteri, quindi il 2 ° deve elaborarlo?

O prima di tutto definire qualche funzione nello script AWK, che divide le linee in variabili in base all'ingresso -. Vorrei andare in questo modo, per l'eventuale riutilizzo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top