Procesamiento de texto para extraer campos de estructura.

Procesamiento de texto para extraer campos de estructura.

Estoy intentando extraer campos de una estructura, por ejemplo.

  typedef struct newstruct {
  long id;            
  uint32_t vtid;      
  struct HN* next;
} HashNode;

Quiero usar sed/awk para extraer el nombre de la estructura, seguido de los campos con un delimitador como

newstruct HashNode: long id, uint_32 vtid, struct HN* next

Respuesta1

Es bastante sencillo con awk, quizás factible con sed.

Con awk, tendría un estado que se establece/restablece en cada typedeflínea y concluye en cada línea con una llave derecha. Un guión adecuado awksería así

BEGIN {
    state = 0;
    typedef="";
    fields="";
}
/typedef[ ]+struct/{
    state = 1;
    typedef=$3;
    next;
}
/}.*;/ {
    if (state != 0) {
        sub("^.*}[  ]*","",$0);
        sub(";","",$0);
        sub(",$","",fields);
        printf "%s %s: %s\n", typedef, $0, fields;
        state = 0;
        fields = "";
        typedef = "";
    }
    next;
}
(state == 1){ 
    gsub("[     ]+"," ", $0);
    gsub(";",",",$0);
    fields = fields $0;
    next;
}

donde los corchetes [y ]encierran un espacio y una pestaña (para hacerlo portátil). El guión consta de cuatro partes:

  1. la BEGINacción inicializa variables (no es estrictamente necesario, pero algunos awks hacen cosas ligeramente diferentes con variables no inicializadas)
  2. el patrón que coincide con la línea con typedef, seguido de espacios en blanco y la palabra struct. Eso espera al menos 3 campos en la línea, usando el tercero como nombre del typedef.
  3. un patrón que coincida con la llave de cierre. En caso de que su archivo contenga otras cosas, la acción verifica si stateestaba configurada. La $0es la línea actual. La primera sustitución elimina todo lo que está antes de la palabra que nos interesa y la segunda elimina el punto y coma que la sigue. La tercera sustitución cambia una coma después de la fieldsvariable que proviene de la cuarta acción (a continuación) a una cadena vacía.
  4. un patrón que coincide con todas las demás líneascuando stateEstá establecido. Al igual que la acción anterior, esta utiliza la sustitución para recortar las partes que no se desean, primero reduciendo varios espacios en blanco a uno solo y luego cambiando el punto y coma al final por una coma.

Llame a ese archivo foo.awky a sus datos de entrada foo.inpara usar awk de esta manera:

awk -f foo.awk <foo.in

Si quisieras unir líneas como esta:

struct foo {

en vez de

typedef struct foo {

entonces el patrón podría escribirse

/^([  ]*typedef)?[  ]+struct[  ]+/{

(nuevamente, con un espacio literal y tabulación entre corchetes). Los paréntesis marcan unagrupoy el signo de interrogación ?dice que se repita cero o más veces. (El{en la línea en realidad denota el comienzo de laacción, pero lo dejé allí para que coincida con la línea del script dado).

Otras lecturas:

Respuesta2

sed -rn '
/typedef struct ([[:alnum:]_]+)\s+\{/!b
s//\1/; h
:X
n 
/}\s+([[:alnum:]_]+)/{
    s//\1/
    H
    g
    s/;//g
    s/(.*)\n(.*)\n(.*)\n(.*)\n(.*)/\1 \5: \2, \3, \4/
    p;b
}
s/\s*(.+);\s*/\1/
H
bX
' file

newstruct HashNode: long id, uint32_t vtid, struct HN* next

información relacionada