grep 패턴을 일치시킨 후 전체 파일을 편집하는 방법은 무엇입니까?

grep 패턴을 일치시킨 후 전체 파일을 편집하는 방법은 무엇입니까?

단순화하기 위해 패턴을 일치시킨 후 전체 파일을 편집하고 싶습니다. 파일 예는 다음과 같습니다.

$ cat file
ip=x.x.x.a
mask=255.0.0.0
host=a
ip=x.x.x.b
mask=255.0.0.0
host=b
ip=x.x.x.c
mask=255.0.0.0
host=c
ip=x.x.x.x
blahblah
mask=255.0.0.0
host=d

호스트 c의 IP를 편집하고 싶지만 변수가 있을 수 있으므로 값을 모른다고 가정해 보겠습니다. 해당 줄을 인쇄하는 grep host c데 사용 하면 -B2원본 파일에서 편집할 수 없습니다! 또 다른 점은 행이 호스트 d의 경우와 같은 구조를 갖지 않을 수 있다는 것입니다. ipmask정보 사이에 일부 텍스트가 있으므로 IP 패턴이 항상 내 검색 패턴보다 2줄 앞선다고 가정할 수 없습니다.

계속해서 IP를 모르기 때문에 직접 grep할 수는 없지만 대신 호스트를 검색하고 이 일치 전에 행을 편집하여 IP 값을 변경해야 합니다. 어떻게 해야 하나요?

답변1

파일을 뒤로 탐색하면 훨씬 쉬워집니다. 다행히도 이 작업은 쉽게 수행할 수 있습니다 tac(역방향 작업임 cat). 그런 다음 비교적 간단한 awk스크립트를 사용하여 원하는 스크립트를 찾아 host변경할 수 있습니다 ip.

$ tac input | awk -v OFS="=" -v myip="changed_address" -v myhost="d" -F"=" '$1 == "host" { if( $2 == myhost ) { sw = "on" } else { sw="off" } } sw == "on" && $1 == "ip" { $2=myip } { print $0 }' | tac
ip=x.x.x.a
mask=255.0.0.0
host=a
ip=x.x.x.b
mask=255.0.0.0
host=b
ip=x.x.x.c
mask=255.0.0.0
host=c
ip=changed_address
blahblah
mask=255.0.0.0
host=d

awk어떻게 작동하는지 자세히 설명하겠습니다 .

먼저 몇 가지 변수를 선언합니다. 각 변수는 for host이고 새 값은 다음과 같습니다 ip.

-v myip="changed_address" -v myhost="d"

또한 입력 및 출력에 대한 필드 구분 기호를 선언합니다.

-v OFS="=" -F"="

이제 실제 awk스크립트 자체는 다음과 같습니다.

$1 == "host" {             // If we see the "host" line..
  if( $2 == myhost ) {     // And it matches the one we're looking for..
    sw = "on"              // Set a flag to swap the next IP
  } else { 
    sw="off"               // Otherwise, unset the flag
  }
} 

sw == "on" && $1 == "ip" { // If the flag is set and this is an IP line.. 
    $2=myip                // Swap in the new IP 
}

{
   print $0                // Finally, print out the processed line
}

모든 작업이 완료되면 tac다시 사용하여 되돌리고 앞으로 다시 이동합니다.

답변2

그러면 호스트와 연결된 IP가 c다음으로 변경됩니다 1.2.3.4.

$ sed 's/^ip/\nip/' file | perl -00pe 'if(/\nhost=c\n/){s/ip=\S+/ip=1.2.3.4/} s/\n\n/\n/' 
ip=x.x.x.a
mask=255.0.0.0
host=a
ip=x.x.x.b
mask=255.0.0.0
host=b
ip=1.2.3.4
mask=255.0.0.0
host=c
ip=x.x.x.x
blahblah
mask=255.0.0.0
host=d

설명하다:

  • sed 's/^ip/\nip/' file\n:로 시작하는 각 줄에 추가 개행 문자( )를 추가합니다 ip. 나는 이것이 의 모든 구현에서 작동하지 않을 수 있다고 생각하므로 sed, 당신의 구현이 이것을 지원하지 않는다면 sed명령을 로 바꾸십시오 perl -pe 's/^ip/\nip/'. Perl의 "단락 모드"(아래 참조)를 사용하려면 이것이 필요합니다.

  • perl -00pe: -00Perl이 "단락 모드"에서 실행되도록 합니다. 여기서 "줄"은 두 개의 연속적인 개행으로 정의됩니다. 이를 통해 각 호스트의 블록을 "라인"으로 처리할 수 있습니다. -pe"주어진 스크립트를 적용한 후 각 줄을 인쇄합니다 " 를 의미합니다 -e.

  • if(/\nhost=c\n/){s/ip=\S+/ip=1.2.3.4/}: 이 "라인"(부분)이 개행 문자와 일치하고 그 뒤에 문자열이 온 host=c다음 또 다른 개행 문자가 오는 경우 ip=이를 공백이 아닌 문자( ) 1개 이상으로 바꿉니다.\S+ip=1.2.3.4

  • s/\n\n/\n/각 개행 문자 쌍을 단일 개행 문자로 대체하여 원본 파일의 형식을 복원합니다.

파일을 변경하려면 다음을 사용할 수 있습니다.

tmp=$(mktemp); sed 's/^ip/\nip/' file > $tmp; 
perl -00pe 'if(/\nhost=c\n/){s/ip=\S+/ip=1.2.3.4/} s/\n\n/\n/' $tmp > file

답변3

또 다른 옵션은 다음 주소로 몇 가지 명령을 보내는 것입니다 ed.

h=c
ed -s file <<< $'/^host='"${h}"$'$\n?^ip=\nc\nip=new.ip.here\n.\nw\nq' > /dev/null

기본 아이디어는 개행으로 구분된 명령 목록(ANSI C 인용 문자열 두 개)에서 파일과 파이프를 편집하고, $' ... '주어진 호스트(변수에서 $h)를 검색한 다음 ip=Make it new로 시작하는 줄을 역방향으로 검색한 다음 저장하는 것입니다. 그리고 종료합니다 ed. 줄 바꿈( )으로 구분된 \n명령은 다음과 같습니다.

  1. /^host=... $h $-- ( ) 행으로 시작하는 문자열 검색을 시작하고 ( ) /내용을 검색한 다음 마지막으로 ( ) 행의 끝을 검색합니다. 호스트가 정확히 일치하지 않는 경우 줄 끝 요구 사항을 완화하세요.host=^$h$

  2. ?^ip=-- 이제 일치하는 줄에 있으므로 ip=줄의 시작 부분에 있는 텍스트를 거꾸로 검색합니다.

  3. c-- 이 줄을 바꾸세요

  4. 텍스트 삽입ip=new.ip.here

  5. .-- 삽입된 텍스트 끝

  6. w--디스크에 파일 쓰기

  7. q——편집 종료

-s파일을 열고 저장할 때 방출되는 바이트 수를 묵음 으로 호출하여 ed를 호출합니다 . 검색 중인 및 행이 발견되면 전체 명령을 리디렉션하여 /dev/null기본 출력을 무음으로 설정합니다.edhost=ip=

답변4

$ awk -v host=c -v newip=zzz.zzz.zzz.zzz '$0 ~ "^host=" host "$" { print; getline; $0 = sprintf("ip=%s\s", newip) }; 1' file
ip=x.x.x.a
mask=255.0.0.0
host=a
ip=x.x.x.b
mask=255.0.0.0
host=b
ip=x.x.x.c
mask=255.0.0.0
host=c
ip=zzz.zzz.zzz.zzzs
blahblah
mask=255.0.0.0
host=d

이는 특정 호스트의 IP 주소를 변경하려고 하며 IP 주소 줄이 항상 host=해당 호스트의 줄 뒤에 나타난다고 가정합니다.

프로그램은 awk두 개의 변수와 를 설정하여 명령줄에서 호스트 이름과 새 IP 주소를 얻습니다. 그런 다음 코드는 지정된 호스트 이름에 해당하는 행을 찾고 다음 행(해당 행)을 읽고 삭제한 다음 새 IP 주소를 사용하여 새 행을 만듭니다. 데이터(수정되거나 수정되지 않은)는 프로그램의 꼬리에 의해 출력됩니다.awkhostnewiphost=ip=ip=1

관련 정보