정규식 일치 후 줄을 검색하고 바꾸려면 "sed"를 사용하십시오.

정규식 일치 후 줄을 검색하고 바꾸려면 "sed"를 사용하십시오.

에서는 더 쉬울 것 같지만 그렇게 할 수 있는지 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

그러기 위해서는 목표선을 본 횟수를 세어야 합니다. 불행히도 무엇이든 계산하는 것은 sedPITA입니다. 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 commandsb-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

관련 정보