이것은 여기서 묻고 답한 질문의 확장입니다.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 할 필요가 없습니다$
.