특정 정규식을 포함하지만 그 이상은 포함하지 않는 들여쓰기되지 않은 줄 아래에 들여쓰기된 텍스트 블록을 제거하려면 sed를 어떻게 얻을 수 있습니까?

특정 정규식을 포함하지만 그 이상은 포함하지 않는 들여쓰기되지 않은 줄 아래에 들여쓰기된 텍스트 블록을 제거하려면 sed를 어떻게 얻을 수 있습니까?

저는 거의 하루종일 GPT, sed 문서, 정규식을 다루느라 애쓰고 있습니다. Cisco 접두사 목록 구성이 포함된 파일을 구문 분석하고 주어진 정규식 목록 이름과 일치하지 않는 목록을 인쇄하고 해당 목록의 콘텐츠나 동일한 목록 이름 아래에 들여쓰기된 콘텐츠를 무시하려고 합니다.

예를 들어 내 파일은 다음과 같습니다(네트워크 난독화).

ip prefix-list ispA_in_pref-150
ip prefix-list ispB_in_pref-100
ip prefix-list ispC_out_deny
    seq 10 permit 23.1.24.3/24
ip prefix-list ispD_in_pref-50
    seq 10 permit 5.2.3.4/24
ip prefix-list ispD_in_pref-100
    seq 10 permit 4.18.27.58/24
ip prefix-list ispE_out_deny
    seq 10 permit 9.2.3.4/24
    seq 20 permit 4.4.4.1/24
ip prefix-list ispF_out_deny
    seq 10 permit 2.2.3.4/24
    seq 20 permit 28.2.3.1/24
ip prefix-list ispG_out_deny
    seq 10 permit 4.2.3.4/24
ip prefix-list ispH_in_pref-150
ip prefix-list ispI_out_deny
    seq 10 permit 3.2.3.4/24

내가 원하는 것은:

ip prefix-list ispA_in_pref-150
ip prefix-list ispB_in_pref-100
ip prefix-list ispD_in_pref-50
    seq 10 permit 5.2.3.4/24
ip prefix-list ispD_in_pref-100
    seq 10 permit 4.18.27.58/24
ip prefix-list ispH_in_pref-150

내가 계속 얻는 것은 다음과 같은 출력입니다(그리고 sed 명령):

:~$ sed -e '/deny/{:a;N;/\n.*seq.*/!ba;d}' file
ip prefix-list ispA_in_pref-150
ip prefix-list ispB_in_pref-100
ip prefix-list ispD_in_pref-50
    seq 10 permit 5.2.3.4/24
ip prefix-list ispD_in_pref-100
    seq 10 permit 4.18.27.58/24
    seq 20 permit 4.4.4.1/24
    seq 20 permit 28.2.3.1/24
ip prefix-list ispH_in_pref-150

완전히 다른 목록에서 다른 2개의 "seq 20" 행을 가져오는 방법에 주목하세요.

GPT의 경우 다음 예가 제공됩니다.

Line 1
Pattern Line
Line 2
This is a line below Line 2
Another line below Line 2
Pattern Line
Line 3

결과는 다음과 같습니다.

:~$ sed -e '/Line 2/{:a;N;/\nPattern.*/!ba;d}' input_file
Line 1
Pattern Line
Line 2
Line 3

나는 이것을 재현할 수 있었지만 ACL 파일을 사용하지는 않았습니다.

sed에 컨텍스트를 제공하기 위해 버퍼를 유지함으로써 이 작업을 수행할 수 있는 방법이 있다고 맹세할 수 있지만 게시물을 재배치할 수 없으므로 실행된 다른 명령이 있는지 알 수 없습니다. sed는 네트워크 표기법의 "/"로 인해 혼동을 일으키나요? 더 좋은 방법이 있나요?

답변1

이상한:

$ awk '/deny/ { deny=1; next }
       /^ip/  { deny=0; print; next }
       !deny' < data
ip prefix-list ispA_in_pref-150
ip prefix-list ispB_in_pref-100
ip prefix-list ispD_in_pref-50
    seq 10 permit 5.2.3.4/24
ip prefix-list ispD_in_pref-100
    seq 10 permit 4.18.27.58/24
ip prefix-list ispH_in_pref-150

답변2

awk를 사용하십시오.

$ awk '/^ip/{f=/deny/} !f' file
ip prefix-list ispA_in_pref-150
ip prefix-list ispB_in_pref-100
ip prefix-list ispD_in_pref-50
    seq 10 permit 5.2.3.4/24
ip prefix-list ispD_in_pref-100
    seq 10 permit 4.18.27.58/24
ip prefix-list ispH_in_pref-150

답변3

직면한 문제는 Cisco 접두사 목록이 본질적으로 계층적이며 정규식만으로는 sed상당히 복잡해질 수 있기 때문입니다. 단일 라인 패턴 일치 및 교체에 더 적합합니다. 원하는 결과를 얻으 려면 awk. perl다음을 사용하는 솔루션은 다음과 같습니다 awk.

awk '
  /^ip prefix-list/ {  # If the line starts with "ip prefix-list"
    list_name = $3   # Set list_name to the third field
    match(list_name, /^.*\//)  # Check if list_name contains a slash
    if (RSTART) {  # If it does, it's a main list, print it
      print
      in_main_list = 1
    } else {  # Otherwise, it's a sub-list, ignore it
      in_main_list = 0
    }
  }
  /^ / && in_main_list {  # If the line starts with a space (sub-list) and in_main_list is true
    next  # Skip this line
  }
  in_main_list {  # If we are inside a main list, print the line
    print
  }
' file

스크립트는 다음을 수행합니다 awk.

  1. "ip prefix-list"로 시작하는 줄을 만나면 목록 이름에 슬래시("/")가 포함되어 있는지 확인합니다. 그렇다면 기본 목록으로 처리되고 스크립트는 이를 인쇄하고 in_main_list플래그( )를 true로 설정합니다.

  2. 줄이 공백으로 시작하고 in_main_listtrue이면 해당 줄을 건너뜁니다(하위 목록 항목 무시).

  3. true 인 경우 in_main_list행을 인쇄합니다.

이 스크립트는 하위 목록 항목을 필터링하여 원하는 출력을 제공해야 합니다.

관련 정보