`sed` 또는 `awk`를 사용하여 두 가지 다른 패턴이 일치한 후에만 파일에서 텍스트를 찾고 바꿉니다.

`sed` 또는 `awk`를 사용하여 두 가지 다른 패턴이 일치한 후에만 파일에서 텍스트를 찾고 바꿉니다.

이것은 여기서 묻고 답한 질문의 확장입니다.sed를 사용하여 처음 발생하는 경우에만 패턴 일치 후 파일에서 텍스트 찾기 및 바꾸기

문제는 찾기 및 바꾸기를 수행해야 하지만오직pattern1의 첫 번째 발생 이후에는 pattern2. 여기서 pattern3찾기 및 바꾸기가 수행되어야 합니다.

연결된 질문의 샘플 파일 변형을 사용합니다.

Server 'Test AB'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test AB'
    option type 'sb'
    option port '1234'
    option timeout '60'

Server 'Test EF'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test GH'
    option type 'sa'
    option port '1234'
    option timeout '60'

나는 이것이 필요하다:

Server 'Test AB'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test AB'
    option type 'sb'
    option port '9876'
    option timeout '60'

Server 'Test EF'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test GH'
    option type 'sa'
    option port '1234'
    option timeout '60'

처음 두 Server이름은 동일합니다. option type서버마다 다릅니다 . 특정 Server이름( Test AB)을 일치시킨 다음 option type( sb)을 일치시키고 포트 번호를 변경해야 합니다.

여러 패턴을 논리적 AND.

어떤 팁이 있나요? sed또는 awk솔루션이 선호됩니다(그러나진짜도전하고 싶다면 순수 BASH 대체 방법으로 시도해 보세요. BASH 5 이상은 괜찮습니다). 감사합니다.

답변1

sed양식에 주소 범위를 지정할 수 있습니다 addr1,addr2. 연결된 답변은 범위를 사용합니다. 이제 범위를 중첩해야 합니다.

sed "
/^Server 'Test AB'$/,/^$/ {
/option type 'sb'/,/option port '/ s/option port '.*'/option port '2222'/
}" file

이는 다음을 의미합니다. 라인부터 Server 'Test AB'다음 빈 라인까지(및 포함) 내부에 코드를 적용합니다 {}.

그리고 내부의 코드는 {}다음을 의미합니다. 포함하는 줄부터(및 포함) 명령을 적용하는 option type 'sb'줄을 포함하는 줄까지(포함) .option port 's/…/…/

그리고 명령은 다음을 의미합니다. 각 줄에서 ( 0개 이상의 문자와 탐욕적으로 일치하는) s/…/…/의 첫 번째 항목을 로 바꿉니다 .option port '.*'.*option port '2222'

노트:

  • 다행스럽게도 범위를 끝내는 데 사용할 수 있는 빈 줄이 있습니다. 그것들이 없으면 우리는 Server에서 까지의 범위를 지정하고 싶은 유혹을 받게 될 것입니다 Server. 문제는 Server 'Test AB'의 다음 발생까지 의 첫 번째 범위 Server에 두 번째 발생이 포함된다는 것입니다 Server 'Test AB'. sed동일한 addr1,addr2코드 조각으로 감지된 범위는 겹칠 수 없습니다 . 실제로 두 번째 발생은 Server 'Test AB'새 범위의 시작으로 처리되지 않으므로 내부 코드는 {}이 섹션의 줄에 대해 실행되지 않습니다.

  • ^$각각 줄의 시작과 끝을 위한 앵커입니다. 와 함께 사용했지만 Server 'Test AB'의도적으로 와 함께 사용하지 않았습니다 option type 'sb'. 필요에 맞게 코드를 조정하세요.

  • 데이터에 작은따옴표가 포함되어 있으므로 큰따옴표를 사용했습니다. 일반적으로 $큰따옴표로 이스케이프해야 하지만 여기서는 /각 바로 뒤에 $; $/은 쉘 변수의 유효한 이름도 아니고 쉘이 확장하려는 이름도 아니므로 escape 할 필요가 없습니다 $.

관련 정보