단일 또는 여러 줄의 두 문자열 사이에서 데이터를 가져오는 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

여기서 스위치는 모듈 이름입니다.

위의 예에서 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이 모두 같은 행에 있기 때문에 출력에 언급된 모든 데이터를 가져올 수 없습니다.

내 배쉬 코드는

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를 사용하여 다중 문자 , RS단어 경계를 나타내고 약어를 사용하십시오 .RT\<\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   

귀하의 예제에 it 이 있기 때문에 추가 사항이 (있습니다 . 제 생각에는 오타라고 생각됩니다.mod_reg_lif(module mod_reg_lif((out, In, clk, rst )

여기서 아이디어는 grep에서 PCRE 모드를 사용하여기대된다이를 통해 공백이 아닌 문자( \S+), 0개 이상의 공백 문자( \s*), 그리고 (( (?=\())를 찾을 수 있습니다.

옵션이 포함된 grep이 없으면 -P다음을 수행할 수 있습니다.

$ 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

관련 정보