Linux 명령을 사용하여 파일에서 마지막 5개의 문자열을 바꾸고 싶습니다.
조언해주세요.
예:
입력이 예상 출력 으로 ababa ababa ababa ababa ababa ababa
대체되었습니다 .aba
abX
ababa abXba abXba abXba abXba abXba
입력은 실행의 출력 으로 ababa ababa ababa ababa ababa ababa ababa
대체됩니다 .aba
12
ababa ababa 12ba 12ba 12ba 12ba 12ba
참고: 문자열은 여러 줄에 걸쳐 있거나 파일의 어느 위치에나 있을 수 있습니다. 하지만 최근 5경기만 교체하고 싶습니다.
파일에 일치하는 항목이 100개 있으면 마지막 5개 일치 항목이 대체됩니다.
답변1
그리고 perl
:
perl -0777 -pse '
$count = () = /\Q$string\E/g;
s{\Q$string\E}{$count-- > $n ? $& : $replacement}ge
' -- -string='whatever
even multiple
lines' -replacement='whatever as well' -n=5 -- file
표준 출력으로 결과를 보내는 대신 제자리에서 -i
편집할 수 있는 옵션이 추가되었습니다 .file
-p
파일의 모든 레코드에 대해 전달된 표현식sed
의 코드를 평가하는 패턴 입니다.e
-e
-0777
레코드 구분 기호를 불가능한 바이트 값으로 설정하십시오. 즉, 파일의 전체 내용인 단 하나의 레코드만 있음을 의미합니다.-s
-varname=value
변수 값을 매개변수로 전달할 수 있습니다 ./regexp/g
$_ =~ m{regexp}g
는 현재 레코드(in)에 적용되고regexp
정규식이 스칼라 컨텍스트에서 일치하고 일치 목록이 목록 컨텍스트에서 일치하는 경우 true/false를 반환하는 전역 atcher 의 약어입니다 . 여기서 정규 표현식은 다음과 같습니다.m
$_
\Q$string\E
\Q
\E
인용하다$string
so는 정규식 연산자가 포함되어 있어도 리터럴 문자열로 처리됩니다.- 를 사용하면
() = /regexp/g
빈 변수 목록에 할당하여 목록 컨텍스트를 강제로 사용하므로 기본적으로 해당 항목을 삭제하지만 결과는 스칼라 할당에 사용되므로 요소 수와 일치 항목 수가 제공됩니다. 정규식이므로$string
레코드의 발생 횟수(의 전체 내용file
)입니다. s{regexp}{replacement}ge
: 펄 코드 표현식으로 해석되는 전역적 으로 일치하는 .for 를 대체s
합니다 .g
regexp
replacement
e
replacement
condition ? iftrue : iffalse
대부분의 언어에서 발견되는 일반적인 C 삼항 연산자입니다.$count--
$count
이전 증분을 반환합니다 . 일치하는 항목이 포함된 항목< $n
으로 바꾸면 아무 작업도 수행하지 않고 로 바꾸지 않으면 아무 작업도 수행하지 않습니다 .$&
$replacement
답변2
이것은 awk와 sed를 사용하는 한 가지 방법입니다. 다음을 통해 파일에서 문자열 발생 횟수를 계산합니다.
grep -o mystring file1.txt | wc -l
이 숫자가 20이라고 가정해 보겠습니다. 이제 처음 20-5=15 항목을 임의의 문자열로 바꿉니다(예: PWWP).
awk '{for(i=1;i<=NF;i++){if(c<15&&$i=="mystring"){c++;sub("mystring","PWWP",$i)}}}1' file1.txt > file2.txt
sed를 사용하여 file2.txt에서 나머지 일치 항목(5개 항목)을 모두 제거합니다.
sed -i 's/mystring//g' file2.txt
그리고 두 번째 sed 작업으로 원본 파일을 복원합니다.
sed -i 's/PWWP/mystring/g' file2.txt
mv file2.txt file1.txt