Processamento de texto para extrair campos de estrutura

2

Eu estou tentando extrair campos de uma estrutura, por exemplo.

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

Eu quero usar o 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
    
por kris 24.10.2016 / 01:06

2 respostas

2

É bastante simples com awk , talvez possível com sed .

Com awk , você teria um estado definido / redefinido em cada linha de typedef e seria concluído em cada linha com uma chave direita. Um script awk adequado seria parecido com

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;
}

em que os colchetes [ e ] incluem um espaço e uma tabulação (para torná-lo portátil). Existem quatro partes no script:

  1. a ação BEGIN inicializa variáveis (não estritamente necessárias, mas alguns awks fazem coisas ligeiramente diferentes com variáveis não inicializadas)
  2. o padrão que corresponde à linha com typedef , seguido de blank (s) e a palavra struct . Isso espera pelo menos 3 campos na linha, usando o terceiro como o nome do typedef.
  3. um padrão para combinar com a chave de fechamento. Apenas no caso de seu arquivo ter outras coisas, a ação verificará se state foi definido. O $0 é a linha atual. A primeira substituição apaga tudo antes da palavra em que estamos interessados, e a segunda tira o ponto-e-vírgula depois dela. A terceira substituição muda uma vírgula após a variável fields que veio da quarta ação (abaixo), para uma string vazia.
  4. um padrão que corresponde a todas as outras linhas quando state está definido. Como a ação anterior, isso usa a substituição para aparar as partes não desejadas, primeiro reduzindo vários espaços em branco para um único espaço em branco e, em seguida, alterando o ponto-e-vírgula à direita 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 uma tabulação entre colchetes). Os parênteses marcam um grupo e o ponto de interrogação ? diz para repetir isso zero ou mais vezes. (O { na linha denota o início da ação , mas deixei-a lá para corresponder à linha no script fornecido).

Leitura adicional:

por 24.10.2016 / 01:28
0
sed -rn '
/typedef struct ([[:alnum:]_]+)\s+\{/!b
s///; h
:X
n 
/}\s+([[:alnum:]_]+)/{
    s///
    H
    g
    s/;//g
    s/(.*)\n(.*)\n(.*)\n(.*)\n(.*)/ : , , /
    p;b
}
s/\s*(.+);\s*//
H
bX
' file

newstruct HashNode: long id, uint32_t vtid, struct HN* next
    
por 21.01.2017 / 13:12