使用正则表达式和 sed 注释特定行

使用正则表达式和 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 行到最后一行的第一个匹配;。然后,第七行到最后;(分号)。然后,从第 10 行到最后;。然后是第 12 行到最后;

我怎样才能让它按我想要的方式工作?

答案1

使用非贪婪匹配:

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

答案2

使用 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)告诉 sed 不是一次读取一行文件,而是直到找到 NUL 字符为止。由于合理的文本文件永远不会有 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}

    如果模式空间当前包含;,则分支到 label b

  • N

    从文件中读取下一行并将其存储在模式空间中。

  • ba

    分支到标签a

  • :b

    这定义了标签b

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

    如果我们到达这里,这意味着模式空间以包含 的行开始HS55_LH_OPTALL_GND_Z,并以包含 的行结束;。对于这个模式空间,我们将 a 放在/*第一个前面H,将 a*/放在第一个后面;

相关内容