sed 命令的 bash 脚本用于获取单行或多行之间的两个字符串之间的数据

sed 命令的 bash 脚本用于获取单行或多行之间的两个字符串之间的数据

我有一些文件(.v.gz)。文件中存在的数据如下所示

句法:

module **module_name**(out, In, clk, rst )
statement 1
statement 2
   :
   :
statement n
endmodule

实际数据是

文件

module mod_reg_lif(out, In, clk, rst )  #
statement 1
statement 2
   :
   :
statement n
endmodule

module 
    dff_reg_net(out, In, clk, rst )  
statement 1
statement 2
   :
   :
statement n
endmodule

module 
   dat_log_out (out, In, clk, rst ) 
statement 1
statement 2
   :
   :
statement n
endmodule

module rest_wire_lib  (out, In, clk, rst ) 
statement 1
statement 2
   :
   :
statement n
endmodule

实际文件包含相似类型的多个数据

module switch(in1, datainready1, atainready) 
always @(posedge clk) 
begin 
  if (reset == 1)
  begin 
    counter<= 0;
      datainreadyl<= 0;
    if(counter ==0) 
      dataoutready<= 0;
   end 
endmodule

这里的 switch 是模块名称

上面的例子请检查 module_names 是mod_reg_lif,dat_log_out,dff_reg_net,rest_wire_lib,

考虑之后模块作为 模块名称(在同一行或下一行中)直到如果它位于同一行或下一行,则会发生。在输出中,我只想要这样的模块名称

mod_reg_lif   
dat_log_out 
dff_reg_net
rest_wire_lib  

我得到什么输出

mod_reg_lif   
rest_wire_lib 

我无法获取输出中提到的所有数据,因为 module 和 module_name 都存在于同一行中。

我的 bash 代码是

for file in *.v.gz;
do
  zgrep -A1 "^module" "$file" | sed -n -e 's/^\(module \)*\(.*(.*)\).*$/\2/p' | cut -f1 -d"(" > $(basename "$file" .v.gz).txt
done

请纠正我的sed -n -e 's/^(模块)(.(.))。$/\2/p'命令我不知道如何修复。

ps:如果对问题有疑问,请评论。

答案1

这可能就是您想要做的,使用 GNU awk 表示多字符RSRT\<字边界,并\s使用简写表示[[:space:]]

$ zcat *.v.gz | awk -v RS='\\<module\\s+[^[:space:](]+' 'RT{$0=RT; print $2}'
mod_reg_lif
dff_reg_net
dat_log_out
rest_wire_lib

答案2

从您给出的示例来看,括号仅出现在模块名称之后,并且模块名称没有空格。如果是这样,你可以这样做:

$ zgrep -oP '\S+\s*(?=\()' file.v.gz 
mod_reg_lif(
dff_reg_net
dat_log_out 
rest_wire_lib   

额外的(mod_reg_lif(那里是因为你的例子有module mod_reg_lif((out, In, clk, rst ),我认为这是一个错字。

这里的想法是在 grep 中使用 PCRE 模式来获取前瞻这让我们可以查找非空白字符 ( \S+),后跟 0 个或多个空白字符 ( \s*),然后是(( (?=\())。

如果你没有带-P选项的 grep,你可以这样做:

$ zgrep -o '[^[:blank:]]*[[:blank:]]*(' file.v.gz | sed 's/ *(//g'
mod_reg_lif
dff_reg_net
dat_log_out
rest_wire_lib

如果你不能使用括号,如果你的文件中还有其他地方可能出现括号,所以你需要使用字符串来module标识模块名称,你可以尝试:

$ zcat file.v.gz | perl -007ne 'print join("\n",(/\bmodule\s*(\S+?)\s*\(/gs)),"\n"; '
mod_reg_lif
dff_reg_net
dat_log_out
rest_wire_lib

请注意,这会将整个文件加载到内存中,这对于大文件可能是一个问题。


最后,您还可以使用awk,将记录分隔符设置为两个空字符串,这会导致 awk 在“段落模式”下工作,其中记录(行)由两个连续的换行符定义。然后,删除一行中第一个括号后面的所有内容并打印第二个字段:

$ zcat file.v.gz | awk 'BEGIN{RS=""}{sub(/\(.*/,"");print $2; }'
mod_reg_lif
dff_reg_net
dat_log_out
rest_wire_lib

相关内容