Comente linhas específicas usando expressões regulares e sed

1

Eu tenho um arquivo verilog muito grande (~ 350 MiB). Nessa, eu quero comentar nomes de módulos específicos. Então eu peguei um arquivo de exemplo e tentei minha expressão regular nele.

Arquivo de amostra (abc): -

module util_minor_rev_id(minor_rev);
 output [3:0] minor_rev;
 wire [3:0] minor_rev;
 wire n_15, n_16, n_17, n_18, n_19, n_20, n_21, n_22;
 HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id0(.A (1'b1), .Z
      (minor_rev[0]));
 HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id1(.A (1'b1), .Z
      (minor_rev[1]));
xyz
HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
      (minor_rev[2]));
HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
      (minor_rev[3]));
endmodule

Eu quero comentar as linhas contendo HS55_LH_OPTALL_GND_Z till ; , então a saída deve ser como

module util_minor_rev_id(minor_rev);
 output [3:0] minor_rev;
 wire [3:0] minor_rev;
 wire n_15, n_16, n_17, n_18, n_19, n_20, n_21, n_22;
/*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id0(.A (1'b1), .Z
     (minor_rev[0]));*/
/*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id1(.A (1'b1), .Z
     (minor_rev[1]));*/
xyz
/*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
      (minor_rev[2]));*/
/*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
      (minor_rev[3]));*/
endmodule

Primeiro, estou tentando verificar meu padrão usando expressão regular e grep. Eu tive problema usando a busca de padrão de múltiplas linhas. Então eu pesquisei e descobri que pcregrep é meu amigo.

pcregrep -Mno '^\s\*HS55_LH_OPTALL_GND_Z.*(\n|.)+;$' abc

Mas a saída é: -

5:  HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id0(.A (1'b1), .Z
       (minor_rev[0]));
  HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id1(.A (1'b1), .Z
       (minor_rev[1]));
xyz
HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
       (minor_rev[2]));
  HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
       (minor_rev[3]));
7:  HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id1(.A (1'b1), .Z
       (minor_rev[1]));
xyz
HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
       (minor_rev[2]));
  HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
       (minor_rev[3]));
10:HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
       (minor_rev[2]));
  HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
       (minor_rev[3]));
12:  HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
       (minor_rev[3]));

Acho que é a primeira correspondência da quinta linha até a última ; . Então, a 7ª linha até a última ; (ponto-e-vírgula). Então, a 10ª linha até o último ; . E depois a 12ª linha até a última ;

Como faço para que funcione como eu quero?

    
por dev vaibhav 01.09.2016 / 08:19

2 respostas

1

Use correspondência não-gananciosa:

pcregrep -Mno '^\s*HS55_LH_OPTALL_GND_Z.*(\n|.)*?;$' file

Saída:

5:      HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id0(.A (1'b1), .Z
           (minor_rev[0]));
7:      HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id1(.A (1'b1), .Z
           (minor_rev[1]));
10:HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
           (minor_rev[2]));
12:      HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
           (minor_rev[3]));

Você também pode comentar as linhas com o Vim:

:%s!^\s*\zsHS55_LH_OPTALL_GND_Z\_.\{-};$!/* & */!

Resultado:

module util_minor_rev_id(minor_rev);
    output [3:0] minor_rev;
    wire [3:0] minor_rev;
    wire n_15, n_16, n_17, n_18, n_19, n_20, n_21, n_22;
    /* HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id0(.A (1'b1), .Z
        (minor_rev[0])); */
    /* HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id1(.A (1'b1), .Z
        (minor_rev[1])); */
xyz
/* HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
        (minor_rev[2])); */
    /* HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
        (minor_rev[3])); */
    endmodule
    
por 01.09.2016 / 08:37
0

Usando o GNU sed

Isso parece comentar as linhas que você deseja:

sed -z 's|HS55_LH_OPTALL_GND_Z[^;]*;|/*&*/|g' abc

Por exemplo:

$ sed -z 's|HS55_LH_OPTALL_GND_Z[^;]*;|/*&*/|g' abc
module util_minor_rev_id(minor_rev);
      output [3:0] minor_rev;
      wire [3:0] minor_rev;
      wire n_15, n_16, n_17, n_18, n_19, n_20, n_21, n_22;
      /*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id0(.A (1'b1), .Z
           (minor_rev[0]));*/
      /*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id1(.A (1'b1), .Z
           (minor_rev[1]));*/
xyz
/*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
           (minor_rev[2]));*/
      /*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
           (minor_rev[3]));*/
    endmodule

A opção -z (GNU apenas) diz ao sed para ler o arquivo não em uma linha por vez, mas até encontrar um caractere NUL. Como arquivos de texto sensatos nunca têm um caractere NUL, isso tem o efeito de ler o arquivo inteiro de uma só vez.

O texto acima usa um único comando substituto para colocar /* e */ em torno das linhas de interesse.

Para alterar o arquivo no local:

sed -i.bak -z 's|HS55_LH_OPTALL_GND_Z[^;]*;|/*&*/|g' abc

Usando outro sed

Para BSD / OSX ou outro sed:

sed '/HS55_LH_OPTALL_GND_Z/{:a; /;/{bb}; N; ba; :b; s|H|/*H|; s|;|;*/|;}' abc

Por exemplo:

$ sed '/HS55_LH_OPTALL_GND_Z/{:a; /;/{bb}; N; ba; :b; s|H|/*H|; s|;|;*/|;}' abc
module util_minor_rev_id(minor_rev);
      output [3:0] minor_rev;
      wire [3:0] minor_rev;
      wire n_15, n_16, n_17, n_18, n_19, n_20, n_21, n_22;
      /*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id0(.A (1'b1), .Z
           (minor_rev[0]));*/
      /*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id1(.A (1'b1), .Z
           (minor_rev[1]));*/
xyz
/*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id2(.A (1'b1), .Z
           (minor_rev[2]));*/
      /*HS55_LH_OPTALL_GND_Z opt_plug_minor_rev_id3(.A (1'b1), .Z
           (minor_rev[3]));*/
    endmodule

Para alterar um arquivo no local:

sed -i.bak '/HS55_LH_OPTALL_GND_Z/{:a; /;/{bb}; N; ba; :b; s|H|/*H|; s|;|;*/|;}' abc

Limitação: Como nenhum desses comandos sed analisa seu arquivo, pode haver situações em que eles fazem a coisa errada.

Como funciona

  • /HS55_LH_OPTALL_GND_Z/{...}

    Isso seleciona as linhas que contêm HS55_LH_OPTALL_GND_Z e, para essas linhas, os comandos dentro das chaves são executados. Estes comandos estão descritos abaixo.

  • :a

    Isso define um rótulo a .

  • /;/{bb}

    Se o espaço padrão atualmente contiver ; , então ramifique para o rótulo b .

  • N

    Leia na próxima linha o arquivo e armazene-o no espaço padrão.

  • ba

    Filial para rotular a .

  • :b

    Isso define o rótulo b .

  • s|H|/*H|; s|;|;*/|;

    Se chegarmos aqui, isso significa que o espaço de padrão começa com uma linha que contém HS55_LH_OPTALL_GND_Z e termina com uma linha que contém ; . Para esse espaço padrão, colocamos um /* na frente do primeiro H e um */ após o primeiro ; .

por 01.09.2016 / 08:35