에서는 더 쉬울 것 같지만 그렇게 할 수 있는지 awk
궁금합니다 . sed
이것은 내 입력입니다.
line 1
line 2
line 3
line 1
line 2
line 3
line 1
line 2
line 3
line 1
두 번째 정규식을 찾고 그 이후에 발견된 모든 것을 바꾸기 위해 내부 정규식을 작성하고 싶습니다 line 3
. 출력은 다음과 같습니다.
line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced
나는 실제로 이 입력에서만 작동하는 "영리한" 솔루션을 찾고 있는 것이 아닙니다. 일반적인 검색 및 교체 방법이 있는지 알고 싶습니다.뒤쪽에와 일치합니다 sed
.
해결책은 어딘가에 있을 거라고 생각했어요addr
선적 서류 비치, 그런데 할 수 있는 일이라고 설명되어 있지 않은 것 같고 /starting point/,s/...
, 하려고 하면 오류가 납니다.
답변1
그러기 위해서는 목표선을 본 횟수를 세어야 합니다. 불행히도 무엇이든 계산하는 것은 sed
PITA입니다. awk
또는 에서 이 작업을 수행 하는 것이 좋습니다 perl
. 예를 들어:
$ perl -p -e '$found++ if m/line 1/;
next if $found < 2;
s/line 3/replaced/' input.txt
line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced
또는 awk
:
$ awk '/line 1/ { found++ };
found < 2 { print ; next };
{ sub(/line 3/,"replaced") ; print }' input.txt
line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced
이러한 방법은 효과가 있지만 최상의 솔루션, 특히 awk
버전(Perl을 직접 번역한 것임)과는 거리가 멀습니다.
그런데, 두 버전 모두 정규식을 사용하여 검색하고계산, 검색할 정규 표현식 및바꾸다, 대체 문자열, 심지어 필요한 개수까지 스크립트에 하드코딩하는 대신 명령줄 옵션으로 사용할 수 있습니다.
답변2
GNU 사용 sed
(0 주소 1의 경우):
$ sed '0,/^line 1$/b; /^line 1$/,$ s/^line 3$/replaced/' < file
line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced
우리 b
목장나가첫 번째 0,/^line 1/
범위의 경우 이는 두 번째 범위에 /^line 1$/,$
두 번째 발생 항목에 도달할 때만 시작 행이 표시됨 을 의미합니다 line 1
.
n 번째 발생은 다음을 사용하여 awk
더 쉽게 찾을 수 있습니다 .line 1
awk '$0 == "line 1" && ++n == 2, eof {if ($0 == "line 3") $0 = "replaced"}; 1'
(여기에는 eof
초기화되지 않은 다른 변수가 있으므로잘못된대표하다첫 번째,마지막범위에는 끝이 없습니다. 0
리터럴과 동일한 의미이지만 더 읽기 쉽습니다 !skip
.1
진짜현재 레코드를 인쇄하려고 하지만 사용법이 1
관용적이므로 모든 사용자가 인식해야 하며 awk
보다 명확한 대안은 )입니다 {print}
.
1이고 GNU를 가정하므로 표준이 아닌 1 뒤에 추가 sed
할 수도 있습니다 . 우리 는 또 다른 사람 이 필요 합니다 .;more commands
b
-e 'more commands'
sed
답변3
버퍼(패턴 공간)에 카운터를 생성하고 각 라인에서 확인합니다.
sed '
/^line 1/{x;/11/!s/^/1/;x}
x;/11/{x;b1};x;b
:1;s/^line 3$/replaced/
' file
1
카운터 유닛 으로서 사용한다
[업데이트] 더 나은 성능:
sed '
/^line 1$/{x;/11/!s/^/1/;x}
/^line 3$/!b
x;/11/!{x;b}
x;s/.*/replaced/
' file
패턴과 일치하는 행에서만 카운터를 확인하세요 -/^line 3$/
답변4
GNU sed를 사용하면 .
저장된 공간에 개수를 포인트로 저장하여 작업을 수행할 수 있습니다.
sed -e '
/^line 1$/,/^line 1$/{//!b
x;s/^$/./;x;t
:a;n;s/^line 3$/REPLACED/;ba
}
' file
또 다른 가능성은 범위 연산자를 사용하지 않고 GNU sed에서 확장 정규식 모드를 사용하는 것입니다. 여기서 개행 문자는 \n
카운터 역할을 하며 예약된 공간에 저장됩니다.
sed -Ee '
/^line 1$/H
x;s/^(\n{1,2}).*/\1/;x
/^line 3$/G
/\n.{2}/c REPLACED
s/\n//g
' file
Perl은 비슷한 방식으로 동일한 작업을 수행할 수 있습니다.
perl -lpe '
s/^line 3$/$a?"REPLACED":$&/e
unless
m?^line 1$? ... /^line 1$(?{$a++})/;
' file
awk를 사용하면 정규 표현식을 변수와 훌륭하게 결합하고 1씩 증가시킬 수 있습니다.
awk '
1 < ( k += /^line 1$/ ) &&
sub(/^line 3$/,"REPLACED") ||
1' file