web-dev-qa-db-ja.com

正規表現とsedを使用して特定の行にコメントする

非常に大きなVerilogファイル(〜350 MiB)があります。その中で、特定のモジュール名にコメントしたいので、サンプルファイルを取り、正規表現を試してみました。

サンプルファイル(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

HS55_LH_OPTALL_GND_Zを含む行を;までコメントしたいので、出力は次のようになります。

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

私は最初に正規表現とgrepを使用してパターンを検証しようとしています。複数行のパターン検索の使用に問題がありました。だから私はグーグルで検索し、pcregrepが私の相棒であることがわかりました。

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

しかし、出力は次のとおりです。-

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]));

5行目から最後の;までの最初のマッチングだと思います。次に、最後の;(セミコロン)までの7行目。次に、最後の;までの10行目。そして最後の12行目;

どうすれば思い通りに動作させることができますか?

1
dev vaibhav

貪欲でないマッチングを使用する:

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

出力:

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]));

Vimで行にコメントすることもできます:

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

結果:

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
1
Satō Katsura

GNU sedを使用する

これはあなたが望む行をコメントアウトしているようです:

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

例えば:

$ 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

-zオプション(GNUのみ)は、一度に1行ではなく、NUL文字が見つかるまでファイルを読み取るようにsedに指示します。賢明なテキストファイルにはNUL文字が含まれないため、ファイル全体を一度に読み取る効果があります。

上記では、単一の代替コマンドを使用して、対象の行の周囲に/**/を配置しています。

ファイルをインプレースで変更するには:

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

他のsedを使用する

BSD/OSXまたはその他のsedの場合:

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

例えば:

$ 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

ファイルをインプレースで変更するには:

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

制限:これらのsedコマンドはいずれもファイルを解析しないため、間違った処理を行う場合があります。

使い方

  • /HS55_LH_OPTALL_GND_Z/{...}

    これにより、HS55_LH_OPTALL_GND_Zを含む行が選択され、それらの行に対して、中括弧内のコマンドが実行されます。これらのコマンドについて、以下で説明します。

  • :a

    これはラベルaを定義します。

  • /;/{bb}

    パターンスペースに現在;が含まれている場合は、ラベルbに分岐します。

  • N

    ファイルから次の行を読み取り、パターンスペースに保存します。

  • ba

    ラベルaに分岐します。

  • :b

    これはラベルbを定義します。

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

    ここに到達すると、パターンスペースはHS55_LH_OPTALL_GND_Zを含む行で始まり、;を含む行で終わることを意味します。このパターンスペースでは、最初のHの前に/*を置き、最初の*/の後に;を置きます。

0
John1024