Processamento de texto para extrair campos de estrutura

Processamento de texto para extrair campos de estrutura

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 typedeflinha e termina em cada linha com uma chave direita. Um script adequado awkseria 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:

  1. a BEGINação inicializa variáveis ​​(não é estritamente necessária, mas alguns awks fazem coisas ligeiramente diferentes com variáveis ​​não inicializadas)
  2. o padrão que corresponde à linha com typedef, seguido por espaços em branco e a palavra struct. Isso espera pelo menos 3 campos na linha, usando o terceiro como nome do typedef.
  3. um padrão para combinar com a chave de fechamento. Caso seu arquivo contenha outras coisas, a ação verifica se statefoi 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 a fieldsvariável que veio da 4ª ação (abaixo), para uma string vazia.
  4. um padrão que corresponde a todas as outras linhasquando stateestá 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.awke seus dados de entrada foo.inpara 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

informação relacionada