Procesamiento de text para extraer campos de estructura

Estoy tratando de 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 

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

Con awk , tendrías un estado que se configura / restablece en cada línea typedef , y concluye en cada línea con un corsé derecho. Un script awk adecuado se vería como

 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 [ y ] corchetes encierran un espacio y una pestaña (para hacerlo portátil). Hay cuatro partes en el guión:

  1. la acción BEGIN inicializa las 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 blanco (s) y la palabra struct . Eso espera al less 3 campos en la línea, usando el tercero como el nombre de typedef.
  3. un patrón para que coincida con la llave de cierre. En caso de que su file tenga otras cosas, la acción comtesting si se configuró el state . El $0 es la línea actual. La primera sustitución recorta todo antes de la palabra que nos interesa, y la segunda recorta el punto y coma siguiente. La tercera sustitución cambia una coma después de la variable de fields que vino de la 4ta acción (abajo) a una cadena vacía.
  4. un patrón que coincide con todas las otras líneas cuando se establece el state . Al igual que en la acción anterior, esto utiliza la sustitución para recortar las partes que no se desean, primero networkinguciendo múltiples espacios en blanco a un solo espacio en blanco, y luego cambiando el punto y coma final a una coma.

Llame a ese file foo.awk , y sus datos de input foo.in , para usar awk de esta manera:

 awk -f foo.awk <foo.in 

Si quieres unir líneas como esta:

 struct foo { 

más bien que

 typedef struct foo { 

entonces el patrón podría escribirse

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

(nuevamente, con un espacio literal y una pestaña entre corchetes). Los paréntesis marcan un grupo y el signo de interrogación ? dice repetir eso cero o más veces. (El { en la línea en realidad denota el comienzo de la acción , pero lo dejé allí para que coincida con la línea en el guión dado).

Otras lecturas:

  • awk – lenguaje de escaneo y procesamiento de patrones (POSIX)
  • 9.4 Expresiones regulares extendidas (POSIX)
 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