한 파일의 문자열을 다른 파일의 전체 내용으로 바꾸는 sed(또는 awk) 명령을 작성하고 싶습니다.

한 파일의 문자열을 다른 파일의 전체 내용으로 바꾸는 sed(또는 awk) 명령을 작성하고 싶습니다.

한 파일의 문자열을 다른 파일의 전체 내용으로 바꾸는 sed(또는 awk) 명령을 작성하고 싶습니다. 콘텐츠를 가져오려는 두 번째 파일에는 한 줄 이상이 있습니다.

$ cat file.txt 
TEXT1 
TEST2 
TEST3 

그리고

$ cat other_file.txt 
there are multiple lines1 
there are multiple lines2 
there are multiple lines3 

나는 출력을 다음과 같이 원한다:

$ cat file3.txt
there are TEXT1 
TEST2 
TEST3 lines1

there are TEXT1 
TEST2 
TEST3 lines2

there are TEXT1 
TEST2 
TEST3 lines3

나는 이것을 시도했습니다 :

sed -i -e '/PLACEHOLDER/ r file' -e s/PLACEHOLDER// otherFile

그러나 그것은 나에게 올바른 출력을 제공하지 않습니다.

"다중" 키워드를 파일의 각 줄에 있는 모든 항목으로 바꾸십시오. 이것이 명확해지기를 바랍니다.

답변1

m4매크로 프로세서를 사용하여 PLACEHOLDER다른 파일이 포함된 매크로를 정의합니다.

$ cat file
foo PLACEHOLDER baz
$ cat otherfile
These are the
multi-line contents
of the other file.
$ m4 -D PLACEHOLDER='include(otherfile)' file
foo These are the
multi-line contents
of the other file.
 baz

otherfile여기에는 최종 개행 문자를 제거하지 않고 있는 그대로의 텍스트가 포함됩니다 .

답변2

모든 Unix 시스템의 모든 쉘에서 awk를 사용하고 요구 사항에 대해 가능한 설명 1개를 제공하십시오(공백으로 구분된 "단어"에서 전체 단어 문자열 일치를 원하면 대체 텍스트에 역참조 메타 문자 또는 기타 일반적으로 문제가 있는 문자가 포함될 수 있습니다. 공백 유지에 신경 쓰지 않으며 대상 단어가 한 줄에 여러 번 나타날 수 있습니다.)

$ cat tst.awk
BEGIN {
    ORS = RS RS
    old = "multiple"
}
NR==FNR {
    new = (NR>1 ? new RS : "") $0
    next
}
{
    for ( i=1; i<=NF; i++ ) {
        if ( $i == old ) {
            $i = new
        }
    }
    print
}

$ awk -f tst.awk file.txt other_file.txt
there are TEXT1
TEST2
TEST3 lines1

there are TEXT1
TEST2
TEST3 lines2

there are TEXT1
TEST2
TEST3 lines3

답변3

사용행복하다(이전 Perl_6)

~$ raku -e 'my @a = dir(test => "Matsuo_Bashō.txt").IO.lines.join("\n"); for lines[0..9] { put S/e/@a[]/ };'  alphabet.txt
a
b
c
d
No one travels
Along this way but I,
This autumn evening.
f
g
h
i
j

Original_File이 교체되었습니다 ==alphabet.txt

~$ raku -e 'for lines[0..9] { .put };' alphabet.txt
a
b
c
d
e
f
g
h
i
j

삽입할 두 번째 파일 ==Matsuo_Bashō.txt

~$ raku -e 'put dir(test => "Matsuo_Bashō.txt").IO.lines.join("\n");'
No one travels
Along this way but I,
This autumn evening.

즉, "삽입"하려는 파일을 가져오고 Raku의 dir()루틴을 사용하여 이를 읽고 @a배열에 저장합니다. 그런 다음 명령줄에서 두 번째 "대상" 파일을 읽습니다(여기서는 알파벳순). "big-S" 교체 연산자 로 교체하면 S///Raku는 결과 문자열을 출력합니다. 참고: 위의 코드는 코드의 첫 번째 항목만 대체합니다. 전역 교체로 만들려면(인식 시퀀스의 모든 항목 교체) 부사를 e추가합니다 . 또는 더 간단하게는 .:globalS:global///S:g///

대체에는 백슬래시가 필요하지 않습니다 @a. 끝에 인덱싱 대괄호를 추가하면 됩니다( @a[]중괄호도 작동합니다. 아래 참조).

바꾸지 않고 대신 첫 번째 파일에서 인식된 시퀀스 다음에 두 번째 파일에 삽입하려면 뒤돌아보기 어설션을 사용하도록 바꾸기 연산자를 변경하고 바꾸기 앞에 개행을 추가하세요.

{ put S/ <?after e> /\n@a[]/ }

#OR

{ put S/ <?after e> /\n{@a}/ }

마지막으로 파일을 slurp한꺼번에 편집할 수 있다는 점에 유의하세요. Raku를 사용하는 루틴은 dir()다음과 같습니다.

  • dir(test => "Matsuo_Bashō.txt").IO.slurp;

...그러나 추가 개행 문자가 출력에 추가됩니다. slurp및를 사용하여 trim-trailing위의 답변을 복제 할 수 있습니다 (아래에서 dir()파일 이름 문자열을 참조하는 간단한 방법은 이를 꺾쇠 괄호로 묶는 것입니다).

~$ raku -e 'my @a = dir(:test<Matsuo_Bashō.txt>).IO.slurp; for lines[0..9] { put S/e/{@a[].trim-trailing}/ };'  alphabet.txt

https://raku.org

관련 정보