텍스트 파일의 패턴 복사 및 바꾸기

텍스트 파일의 패턴 복사 및 바꾸기

다음과 같은 입력 텍스트 파일을 고려해 보겠습니다.

some text …
% BEGIN
blabla
foo bar
blabla
blabla
% END
some text …

그리고 foobar.txt다음과 같은 파일:

2 3
8 9 
1 2

sed(아마도?)를 사용하여 awk이 출력 텍스트 파일을 얻는 가장 쉬운 방법은 무엇입니까 ?

some text …
% BEGIN
blabla
2 3
blabla
blabla
% END
% BEGIN
blabla
8 9
blabla
blabla
% END
% BEGIN
blabla
1 2
blabla
blabla
% END
some text …

답변1

이것은 다음을 사용하는 순수한 awk 접근 방식입니다 getline.

awk '
  /% BEGIN/ {
    s = 1;
  }

  s == 1 {
    b = b == "" ? $0 : b ORS $0
  }

  /% END/ {
    while ((getline repl < "foobar.txt") > 0) {
      tmp = b;
      sub(/foo bar/, repl, tmp);
      print tmp;
    }
    b = "";
    s = 0;
    next;
  }

  s == 0 {
    print;
  }' input

GNU awk를 사용하면 임시 없이 교체할 수 있습니다 gensub. 다음을 사용하세요.

gawk '
  /% BEGIN/ {
    s = 1;
  }

  s == 1 {
    b = b == "" ? $0 : b ORS $0
  }

  /% END/ {
    while ((getline repl < "foobar.txt") > 0) {
      print gensub(/foo bar/, repl, 1, b);
    }
    b = "";
    s = 0;
    next;
  }

  s == 0 {
    print;
  }' input

시험:

$ gawk '
>   /% BEGIN/ {s = 1;}
>   s == 1 {b = b == "" ? $0 : b ORS $0}
>   /% END/ {while ((getline repl < "foobar.txt") > 0) {print gensub(/foo bar/, repl, 1, b);} s = 0; next;}
>   s == 0 {print}' input
some text …
% BEGIN
blabla
2 3
blabla
blabla
% END
% BEGIN
blabla
8 9 
blabla
blabla
% END
% BEGIN
blabla
1 2
blabla
blabla
% END
some text …

답변2

perl -nMFatal=open -e '$l = $_;
   @ARGV and open my $fh, "<", $ARGV[0];
   print +(/^%\hBEGIN/ ? $a=0 : $a++) == 1 ? $l : $_ while <$fh>;
' foobar.txt input.txt

피복재
  • foobar.txt 파일에서 읽은 각 줄에 대해 openinput.txt 파일에 대한 파일 핸들이 있습니다 lexical. $fh어휘적이어야 하는 이유는 foobar.txt에 대한 다음 입력 줄을 읽을 때 자체적으로 닫히기 때문입니다.
  • $ainput.txt에서 이 줄을 보면 % BEGIN카운터를 초기화합니다. 그 다음 한 줄에서는 input.txt의 줄을 foobar.txt의 줄로 바꿉니다.
  • 매개변수의 순서는 foobar.txt, input.txt입니다.
  • 파일을 열 때 오류를 자동으로 처리하는 pragma Fatal.pm이 포함되어 있습니다.
결과
some text --
% BEGIN
blabla
2 3
blabla
blabla
% END
some text --
some text --
% BEGIN
blabla
8 9
blabla
blabla
% END
some text --
some text --
% BEGIN
blabla
1 2
blabla
blabla
% END
some text --

답변3

복잡한세게 때리다+sed해결책:

foobar_replacer.sh스크립트:

#!/bin/bash
head -n1 "$2"  # print the first line

while read -r line
do
    sed '1d;$d;{s/^foo bar$/'"$line"'/g}' "$2"        
done < "$1"

tail -n1 "$2" # print the last line

용법:

bash foobar_replacer.sh foobar.txt input.txt

산출:

some text …
% BEGIN
blabla
2 3
blabla
blabla
% END
% BEGIN
blabla
8 9
blabla
blabla
% END
% BEGIN
blabla
1 2
blabla
blabla
% END
some text …

sed명령 세부정보:

1d;$d;- 첫 번째 행과 마지막 행 삭제input.txt

s/^foo bar$/'"$line"'/gfoo bar- 다음 항목이 포함된 줄을 다음 항목 $line으로 바꿉니다.foobar.txt

답변4

bash스크립트 및 sed사용법. 사용법: , 결과는 새 파일 ./search_and_replace.sh < input.txt에 저장됩니다.output.txt

#!/bin/bash

begin_str="% BEGIN"
end_str="% END"
pattern="foo bar"
write_to_var_flag=0
output_file=output.txt
foobar_file=foobar.txt
begin_to_end_block_var=""

# clean output file if it exist, else create it
> "$output_file"

function read_foobar_file () {
    while read -r line; do
        echo -ne "$begin_to_end_block_var" | sed "s/$pattern/$line/" >> "$output_file"
    done < "$foobar_file"
}

while read -r line; do
    if  [ "$line" == "$begin_str" ]; then
        write_to_var_flag=1
    fi

    if (( $write_to_var_flag )); then
        begin_to_end_block_var+="$line\n"
    else
        echo "$line" >> "$output_file"
    fi

    if [ "$line" == "$end_str" ]; then
        read_foobar_file 
        write_to_var_flag=0
    fi
done

관련 정보