내 디렉토리에 다음 내용의 파일이 많이 있다고 가정해 보겠습니다 *.txt
.texts
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aliquam tincidunt mauris eu risus.
Vestibulum auctor dapibus neque.
나는 그것을 다음으로 바꾸고 싶다재귀적으로.
Vestibulum commodo felis quis tortor.
Ut aliquam sollicitudin leo.
Cras iaculis ultricies nulla.
Donec quis dui at dolor tempor interdum.
왜냐하면 이것은 꽤 큰 교체이기 때문입니다. 하나씩 입력하는 것은 시간이 많이 걸릴 수 있습니다.
그래서 그런 옵션이 있으면 더 좋을 것 같아요.
복사 및 붙여 넣기원본 텍스트를 파일에 넣고 original.txt
원하는 대체 내용을 다른 파일에 넣으세요 update.txt
.
그런 다음 명령을 실행하여 디렉터리에 있는 콘텐츠로 구성된 *.txt
모든 파일을 찾아 해당 콘텐츠로 바꿉니다 .texts
original.txt
update.txt
다음과 같은 간단한 교체와 같은 것입니다.
find texts -name "*.txt" -exec sed -i 's/original/update/g' {} \;
이렇게 하면 수동으로 입력하는 것과 같은 오류가 발생하지 않고 시간도 덜 걸릴 것이라고 생각했습니다.
하지만 이를 달성하려면 어떤 명령을 사용해야 하는지 모르겠습니다. 가능합니까?
하지만 먼저 원본 텍스트의 가용성과 출현 횟수를 확인할 수 있어야 했습니다.
다음과 같은 간단한 검사와 같습니다.
cd texts
grep -r --color=always "original" | wc -l
감사해요.
답변1
저는 sed(또는 awk) 대신 Perl을 사용하겠습니다.
find texts/ -name '*.txt' \
-exec perl -0777 -p -i.bak -e '
BEGIN {
$search = q{Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aliquam tincidunt mauris eu risus.
Vestibulum auctor dapibus neque};
$replace = q{Vestibulum commodo felis quis tortor.
Ut aliquam sollicitudin leo.
Cras iaculis ultricies nulla.
Donec quis dui at dolor tempor interdum.};
};
s/\Q$search\E/$replace/mg' {} +
-0777
Perl에게 전체 파일을 한 번에 "후루룩 소리를 내며" 하나의 긴 문자열로 처리하도록 지시합니다.-p
Perl이 유사하게 작동하도록 만듭니다sed
(그리고 해당-n
옵션을 사용하면 유사하게 작동합니다sed -n
).-i.bak
파일을 "제자리에서" 편집하여.bak
원본 파일을 확장자로 저장합니다. 다시 말하지만sed -i
.백업 복사본이 필요하지 않으면
-i
대신 just를 사용하세요-i.bak
.\Q
Perl 정규식에서는 정규식 특수 문자가 포함된 경우에도 다음 패턴( a 가 나타날 때까지\E
)을 리터럴 문자열로 처리하도록 Perl에 지시합니다.에서
man perlre
:\Q
까지 인용(비활성화) 패턴 메타문자\E
\E
최종 사례 수정 또는 참조 섹션q{}
q
작은따옴표와 정확히 동일한 Perl 인용 연산자를 사용하십시오. 이는 Perl 스크립트가 작은따옴표로 묶인 한 줄의 코드에서 특히 유용합니다(여기서백슬래시로 이스케이프할 수 없습니다.작은따옴표 안의 이스케이프 코드는 무시되기 때문입니다.man perlop
"참조 및 클래스 참조 연산자"를 확인 하고 검색하세요. 또한 참조하십시오perldoc -f q
(perldoc -f qq
큰따옴표 연산자와 비교).
그런데, 단일 파일에서 파일의 perl 부분을 테스트하고 출력을 확인하여 내가 원하는 대로 작동하는지 확인하는 것이 좋습니다(즉, find 없음, 특히 아무것도 없음 -i.bak
).
답변2
데비안 11에서 수행되는 한 가지 방법은 다음과 같습니다:
- 배쉬 v.5.1.4(1)
- tr(GNU Coreutils) v.8.32
- sed (GNU sed) v.4.7
이 스크립트는 다음과 같이 작성되었습니다.
- 문제의 각 파일에
.txt
확장자 가 있다고 가정합니다. .txt
-files와 동일한 디렉터리에서 실행해야 합니다.- 처리하는 동안 각 파일의 이름과 내용을 표시합니다.
- 오류가 발생하더라도 원본 파일을 계속 사용할 수 있도록 하려면 파일을 제자리에서 바꾸는 대신 새 파일을 만드세요. 또한 예를 들어 대체 텍스트를 변경해야 하는 경우 원본 파일에 영향을 주지 않고 단일 명령으로 새로 생성된 파일을 삭제할 수 있습니다.
디렉토리 내용:
pg1@TREX:~/foo$ ls
repla.sh text1.txt text2.txt
텍스트 파일 내용:
pg1@TREX:~/foo$ for i in {1..2}; do cat text$i.txt; echo; done
This is the beginning
of the first text.
These lines
will be replaced.
This is the ending
of the first text.
This is the beginning
of the second text.
These lines
will be replaced.
This is the ending
of the second text.
텍스트 바꾸기:
New lines
that will replace
old lines.
교체.sh:
#!/bin/sh
for i in *.txt; do
echo $i
cat text.txt | tr '\n' '\r' | sed -e 's/These lines\rwill be replaced./New lines\rthat will replace\rold lines./g' | tr '\r' '\n' | tee $i.new
done
결과:
pg1@TREX:~/foo$ ./repla.sh
text1.txt
This is the beginning
of the first text.
New lines
that will replace
old lines.
This is the ending
of the first text.
text2.txt
This is the beginning
of the second text.
New lines
that will replace
old lines.
This is the ending
of the second text.
pg1@TREX:~/foo$ ls
repla.sh text1.txt text1.txt.new text2.txt text2.txt.new
필요에 따라 스크립트를 조정해야 합니다. 예를 들어 수정해야 할 확장자가 다른(또는 확장자가 없는) 텍스트 파일도 있는 경우 또는 파일이 다른 디렉터리에 있는 경우 이를 수용해야 합니다. 주석 처리를 하면 echo $i
처리 중에 파일 이름이 표시되지 않고, 리디렉션 | tee
으로 바꾸면 >
파일 내용이 표시되지 않습니다. 내부 교체를 위해서는 새 파일을 생성해야 하며, 이 파일은 mv
원본 파일을 교체하기 위해 스크립트에 추가되기만 하면 됩니다.
아래 Ed Morton의 의견을 참고하세요.
더 우아하고 긴 단락에 더 적합한 다른 솔루션이 있습니다. 예를 들어이 스택 오버플로 질문이전 단락과 대체 단락이 변수에 있습니다.