
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 typedef
línea y concluye en cada línea con una llave derecha. Un guión adecuado awk
serí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:
- la
BEGIN
acción inicializa variables (no es estrictamente necesario, pero algunos awks hacen cosas ligeramente diferentes con variables no inicializadas) - el patrón que coincide con la línea con
typedef
, seguido de espacios en blanco y la palabrastruct
. Eso espera al menos 3 campos en la línea, usando el tercero como nombre del typedef. - un patrón que coincida con la llave de cierre. En caso de que su archivo contenga otras cosas, la acción verifica si
state
estaba configurada. La$0
es 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 lafields
variable que proviene de la cuarta acción (a continuación) a una cadena vacía. - un patrón que coincide con todas las demás líneascuando
state
Está 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.awk
y a sus datos de entrada foo.in
para 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