
Estou tentando extrair campos de uma estrutura, por exemplo.
typedef struct newstruct {
long id;
uint32_t vtid;
struct HN* next;
} HashNode;
Quero usar sed/awk para extrair o nome da estrutura, seguido pelos campos com um delimitador como
newstruct HashNode: long id, uint_32 vtid, struct HN* next
Responder1
É bastante simples com awk
, talvez possível com sed
.
Com awk
, você teria um estado que é definido/redefinido em cada typedef
linha e termina em cada linha com uma chave direita. Um script adequado awk
seria semelhante
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;
}
onde os [
colchetes ]
e delimitam um espaço e uma tabulação (para torná-lo portátil). Existem quatro partes no script:
- a
BEGIN
ação inicializa variáveis (não é estritamente necessária, mas alguns awks fazem coisas ligeiramente diferentes com variáveis não inicializadas) - o padrão que corresponde à linha com
typedef
, seguido por espaços em branco e a palavrastruct
. Isso espera pelo menos 3 campos na linha, usando o terceiro como nome do typedef. - um padrão para combinar com a chave de fechamento. Caso seu arquivo contenha outras coisas, a ação verifica se
state
foi definido. A$0
é a linha atual. A primeira substituição elimina tudo antes da palavra que nos interessa, e a segunda elimina o ponto e vírgula que a segue. A terceira substituição altera uma vírgula após afields
variável que veio da 4ª ação (abaixo), para uma string vazia. - um padrão que corresponde a todas as outras linhasquando
state
está definido. Como na ação anterior, esta usa substituição para eliminar as partes não desejadas, primeiro reduzindo vários espaços em branco a um único espaço em branco e, em seguida, alterando o ponto-e-vírgula final para uma vírgula.
Chame esse arquivo foo.awk
e seus dados de entrada foo.in
para usar o awk assim:
awk -f foo.awk <foo.in
Se você quisesse combinar linhas como esta:
struct foo {
em vez de
typedef struct foo {
então o padrão poderia ser escrito
/^([ ]*typedef)?[ ]+struct[ ]+/{
(novamente, com um espaço literal e tabulação entre colchetes). Os parênteses marcam umgrupoe o ponto de interrogação ?
diz para repetir isso zero ou mais vezes. (O{
na linha realmente denota o início doAção, mas deixei lá para corresponder à linha do script fornecido).
Leitura adicional:
Responder2
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