![텍스트 파일의 태그를 임의의 새 텍스트로 교체](https://linux55.com/image/59628/%ED%85%8D%EC%8A%A4%ED%8A%B8%20%ED%8C%8C%EC%9D%BC%EC%9D%98%20%ED%83%9C%EA%B7%B8%EB%A5%BC%20%EC%9E%84%EC%9D%98%EC%9D%98%20%EC%83%88%20%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%A1%9C%20%EA%B5%90%EC%B2%B4.png)
일부 텍스트와 새 콘텐츠를 추가해야 하는 위치를 나타내는 표시가 한 줄에 포함된 파일이 있습니다.
foo
bar
%SUBSTITUTE%
foo
한 줄씩 대체하는 내용은 새로운 여러 줄 문자열로 대체되어야 합니다 text="some text"
(문자열을 모른다는 점에 유의하세요. 예를 들어 cat "file" 파일을 읽은 결과일 수 있습니다 text=
). 대체 결과는 다음과 같아야합니다.
foo
bar
some text
%SUBSTITUTE%
foo
작동이 중지 된 작업 버전이 있었습니다 perl
(분명히 Perl 버전 변경으로 인해). 이제 tr
및 같은 표준 유틸리티를 사용하여 sed
해당 줄을 바꾸려고 합니다 . 붙여넣는 문자열에 백슬래시 등 임의의 문자가 포함될 수 있기 때문에 문제가 발생했습니다. 붙여넣기 전에 이러한 문자를 이스케이프 처리하고 싶지 않습니다.
표준 도구를 사용하여 이를 수행하는 안전한 방법이 있습니까? 이 문제에 대해 제가 발견한 다른 문제는 붙여넣은 것으로 알려진 텍스트에 대한 특정 솔루션입니다.
답변1
sed의 GNU 버전이 있는 경우 해당 r
명령을 사용하여 파일에서 읽고 새 내용을 삽입한 다음 표시된 줄을 삭제할 수 있습니다.
sed '/%SUBSTITUTE%/{
r path/to/newcontent
d
}' file
%SUBSTITUTE%
태그를 유지하고 싶다면뒤쪽에삽입하세요. 무엇을 하든 GNU r
확장은 파일 내용을 대기열에 넣을 것이기 때문에 까다롭습니다.끝현재 모드 주기(계속 유지)앞으로명령 을 제거하면 됩니다 d
.) 아마도 가장 쉬운 방법은 파일에 추가하는 것입니다 newcontent
. 다음과 같이 즉시 수행할 수 있습니다.
sed '/%SUBSTITUTE%/{
r /dev/stdin
d
}' file < <(sed '$a %SUBSTITUTE%' path/to/newcontent)
완전히 다른 접근 방식을 사용하면 첫 번째 파일을 분할 %SUBSTITUTE%
한 다음 새 콘텐츠를 추가 할 수 있습니다.
csplit -s file '/%SUBSTITUTE%/'
cat xx00 newcontent xx01
첫 번째 파일의 줄에 대해 bash 루프를 수행하고 태그 문자열이 일치할 때 새 파일의 내용을 캡처 할 수도 있습니다 read
. 그러나 이 포럼에서 제안한 대로 텍스트 처리를 위한 루프를 읽는 것이 이미 불안합니다. 불행히도 둘 다 적절한 솔루션을 제공하지 않습니다.
답변2
이를 사용하는 또 다른 방법이 있습니다 ed
. 태그 앞에 삽입된 모든 항목
(즉, 포함하는 줄 앞):FILE
%SUBSTITUTE%
ed -s originalfile <<< $'/%SUBSTITUTE%/- r FILE\nw\nq'
여기서:
/%SUBSTITUTE%/
: 일치하는 첫 번째 줄에 주소를 설정 %SUBSTITUTE%
-
하거나: -1
한 줄 앞의 주소를 오프셋합니다. : : 쓰기(쓰기 대신 내용을 인쇄하는 것으로 대체됨): 편집기 종료
r FILE
Reads FILE to after the addressed line.
w
originalfile
,p
q
FILE
태그 앞에 !echo "$TEXT"
삽입될 항목 으로 바꾸세요 .$TEXT
export TEXT
ed -s originalfile <<'IN'
/%SUBSTITUTE%/-1 r !echo "$TEXT"
w
q
IN
답변3
나는 다음을 기반으로 솔루션을 찾았습니다 awk
.
text=`cat "filepaste"`
export text;
<"$file" awk '
BEGIN {REPLACE=ENVIRON["text"] "\n%SUBSTITUTE%" }
{gsub(/^%SUBSTITUTE%$/, REPLACE); print}
'
여기서 "filepaste"에는 대체할 콘텐츠가 포함되어 있습니다 %SUBSTITUTE%
. 한 가지 장점은 문자열을 파일에 다시 저장하지 않고도 다양한 셸 도구를 사용하여 문자열을 조작할 수 있다는 것입니다. 환경 변수에서 awk
변수를 읽으면 REPLACE
확장 시 이스케이프 문자가 방지됩니다 text
.
답변4
이제 Perl 솔루션이 있으므로 여기에 또 다른 솔루션이 있습니다. 나는 rep.txt
교체품을 저장하는 데 사용합니다.
$ perl -pe '$re=`cat rep.txt`; chomp($re); s/%SUBSTITUTE%\n/$re/' file.txt
foo
bar
multi
line
string
foo
대상 파일의 각 줄을 읽고( file.txt
), 주어진 스크립트를 -e
여기에 적용하고 인쇄합니다( -p
).