
해당 일치 항목 뒤에 줄을 추가하려면 주어진 문자열이 있는 마지막 줄을 파일에서 검색하세요. 예:
입력:
Apple
Banana
Apple
Orange
Apple
Grapefruit
산출:
Apple
Banana
Apple
Orange
Apple
I am new string replaced at last apple
Grapefruit
답변1
GNU를 사용하면 sed
다음과 같은 작업을 수행할 수 있습니다.
sed ':a;N;$! ba;s/.*\nApple/&\nYour appended line/'
이 패턴은 파일의 끝( 주소)에 도달하지 않은 동안( ) :a;N;$! ba
파일의 줄을 버퍼에 추가합니다 ( with 로 점프 ). 따라서 루프를 종료하면 모든 줄이 버퍼에 있고 검색 패턴은 로 시작하는 마지막 줄까지 전체 파일과 일치합니다 . 대체 문자열 에 전체 일치 항목을 삽입하고 텍스트를 추가합니다.N
$
!
:a
ba
.*\nApple
Apple
&
다른 버전에서도 작동하는 휴대용 솔루션은 sed
다음과 같습니다.
sed -e ':a' -e 'N;$! ba' -e 's/.*\(\n\)Apple/&\1Your appended line/'
여기서 스크립트는 레이블에서 분할되며 \n
대체 문자열(GNU가 아닌 경우 작동이 보장되지 않음 )을 사용하는 대신 참조로 sed
둘러싸인 패턴의 문자열을 참조합니다 .\(\)
\1
답변2
이 예를 봤어요여기
sed -i -e "\$aTEXTTOEND" <filename>
정보:
i: edit files in place
e: add the script to the commands to be executed
$: sed address location
a: append command
TEXTTOEND: text to append to end of file
답변3
귀하의 예제 입력이 fruits.txt
.
"Apple"이 마지막으로 나온 뒤에 한 줄을 삽입하려면 sed
다음과 같이 하면 됩니다.
sed -rz 's/(^(.*\n)?Apple)(\n|$)/\1\ninserted line\n/'
이 -r
옵션을 사용하면 확장 정규식을 사용할 수 있습니다.
이 -z
옵션은 sed
일반 개행 문자 대신 NUL 문자(ASCII 코드 0)를 줄 구분 기호로 사용하도록 지시합니다. 이렇게 하면 전체 텍스트 파일이 한 줄씩 처리되는 대신 한 번에 처리됩니다.
이 sed
명령은 에서 정규식을 s/PATTERN/REPLACEMENT/
검색하여 평가된 문자열로 바꿉니다 .-r
PATTERN
REPLACEMENT
정규식은 (^(.*\n)?Apple)(\n|$)
시작( )부터 줄 바꿈( ) 또는 파일의 끝( )이 뒤따르는 ^
마지막 항목까지 의 줄 수와 일치합니다 .Apple
\n
$
이제 이 전체 일치 항목은 로 대체됩니다 \1\ninserted line\n
. 여기서는 \1
첫 번째 일치 그룹의 원래 콘텐츠, 즉 까지의 모든 항목을 나타냅니다 Apple
. 따라서 실제로 "Apple"이 마지막으로 나타난 바로 뒤에 inserted line
줄 바꿈( )이 앞뒤에 삽입됩니다.\n
이는 "Apple" 줄이 파일의 첫 번째, 마지막 또는 유일한 줄인 경우에도 작동합니다.
예제 입력 파일(동작을 명확하게 하기 위해 예제에 한 줄 추가):
Apple
Banana
Apple
Orange
Apple
Cherry
예제 출력:
Apple
Banana
Apple
Orange
Apple
inserted line
Cherry
결과에 만족하고 fruits.txt
수정 내용을 출력하는 대신 바로 편집하려는 경우 -i
다음 옵션을 추가할 수 있습니다.
sed -irz 's/(^(.*\n)?Apple)(\n|$)/\1\ninserted line\n/'
하지만 해당 파일 끝에 텍스트 한 줄을 추가하려는 경우에는 sed
최적의 도구가 아닙니다.
>>
그런 다음 Bash의 추가 출력 리디렉션을 간단히 사용할 수 있습니다 .
echo "I am new string replaced at last apple" >> fruits.txt
는 >>
왼쪽에 있는 명령의 표준 출력을 취하고( echo
여기서의 명령은 단순히 인수를 표준 출력에 인쇄합니다) 오른쪽에 지정된 파일에 추가합니다. 파일이 아직 존재하지 않으면 생성됩니다.
답변4
이 답변에서는:
- sed+tac(이중 입력 반전)
- 이중 입력이 있는 AWK
- 이중 입력을 사용하는 Perl
- 이중 입력 반전 기능을 갖춘 대체 Perl
sed + 택
이 접근 방식은 3가지 프로세스를 사용합니다. 먼저 파일을 반전하고, sed를 사용하여 첫 번째 일치 항목을 찾고, 첫 번째 일치 후에 원하는 텍스트를 삽입하고, 텍스트를 다시 반전합니다.
$ tac input.txt | sed '0,/Apple/{s/Apple/NEW THING\n&/}' | tac
Apple
Banana
Apple
Orange
Apple
NEW THING
something else
something other entirely
blah
기본 아이디어는 아래에 작성된 대체 Perl 버전과 동일합니다. 행의 역방향 목록에서 첫 번째 일치는 원래 목록의 마지막 일치입니다. 이 접근 방식의 장점은 사용자 입장에서 단순성과 가독성입니다.
이 접근 방식은 작은 파일에는 적합하지만 큰 파일에는 번거롭고 많은 양의 줄을 처리하는 데 상당한 시간이 걸릴 수 있습니다.
AWK
Awk는 당신이 하려는 일에 대해 좀 더 친근하게 다가갈 수 있습니다:
$ awk -v n="AFTER LAST APPLE" 'NR==FNR&&/Apple/{l=NR};NR!=FNR{if(FNR==l){print $0;print n}else print}' input.txt input.t>
Apple
Banana
Apple
Orange
Apple
AFTER LAST APPLE
something else
something other entirely
blah
여기서 기본 아이디어는 입력 파일을 awk에 두 번 제공하는 것입니다. 첫 번째는 마지막 Apple이 있는 위치를 찾고, 두 번째는 첫 번째 반복에서 찾은 마지막 "사과"의 위치를 전달할 때 텍스트를 삽입하는 것입니다.
이 작업을 수행하는 핵심은 NR
(처리된 모든 줄, 총계를 계속 계산) 및 FNR
(현재 파일의 줄 번호) 변수를 평가하는 것입니다. 이 두 파일이 동일하지 않으면 두 번째 파일을 처리하고 있다는 것을 알 수 있으므로 Apple이 마지막으로 발생한 위치를 찾는 첫 번째 단계를 수행했다는 것을 알 수 있습니다.
파일을 두 번 읽으므로 파일 크기에 따라 성능이 달라지지만 파일을 두 번 뒤집을 필요가 없으므로 sed + tac 조합보다 낫습니다.
펄
perl -sne '$t+=1;$l=$. if /Apple/ and $.==$t;
if($t!=$.){if($.==$l){print $_ . $n . "\n";}else{print $_}};
close ARGV if eof;' -- -n="AFTER LAST APPLE" input.txt input.txt
Perl 솔루션은 AWK 솔루션과 동일한 아이디어를 따릅니다. 입력을 두 번 전달하고 파일이 처음 전달될 때 Apple이 마지막으로 나타나는 위치를 찾아 해당 행 번호를 $l
변수에 저장합니다. 여기서 awk와 다른 점은 Perl에는 변수가 없으므로 해당 목적으로 and를 FNR
사용해야 한다는 것 입니다.$t+=1
close ARGV if eof
여기서 또 다른 점은 -s
스위치 Perl을 사용하면 인수를 전달할 수 있다는 것입니다. 이 경우 삽입하려는 문자열이 -n
스위치를 통해 전달됩니다.
대체 펄
Perl에서 이를 수행하는 또 다른 방법이 있습니다. 아이디어는 단순히 파일을 행 배열로 읽고 해당 배열을 뒤집는 것입니다. 역방향 배열의 첫 번째 일치 항목은 원래 줄 목록의 마지막 항목입니다. 따라서 해당 줄 앞에 원하는 텍스트를 삽입하고 목록을 다시 뒤집을 수 있습니다.
$ perl -le '@a1=<>;END{do{push @a2,"NEW LINE\n" and $f=1 if $_ =~ /Apple/ and !$f; push @a2,$_} for reverse(@a1); print reverse(@a2)}' input.txt
Apple
Banana
Apple
Orange
Apple
NEW LINE
something else
something other entirely
blah