출력을 IP 주소별로 정렬할 수 있나요?

출력을 IP 주소별로 정렬할 수 있나요?

저는 수백 개의 네트워크 인터페이스(물론 대부분 가상 인터페이스)를 갖춘 라우터를 가지고 있습니다. 이는 출력을 의미합니다.

ip a

표시되는 라인이 너무 많아 관리 및 분석이 어렵습니다. 항목 1부터 255까지는 항목 번호별로 정렬되지만 256부터 시작하면 정렬 전에 숫자 mod 256이 계산됩니다. 즉, 항목이 인터리브된다는 의미입니다(예: 256, 257, 1, 258, 2...).

# ip a s up
256: veth-99-02@br-vxlan-99-02: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ab:cd:ef:99:88:77 brd ff:ff:ff:ff:ff:ff
    inet 10.2.99.254/24 scope global veth-99-02
       valid_lft forever preferred_lft forever
257: vxlan-22-01: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br-vxlan-20-01 state UNKNOWN group default qlen 1000
    link/ether ab:cd:ef:99:88:77 brd ff:ff:ff:ff:ff:ff
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
258: br-vxlan-22-01: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
    link/ether ab:cd:ef:99:88:77 brd ff:ff:ff:ff:ff:ff
2: eno1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether ab:cd:ef:99:88:66 brd ff:ff:ff:ff:ff:ff

이 출력을 숫자로 올바르게 정렬하는 방법이 있습니까? (여러 줄 항목이므로 | sort -n아니요.)

또는 최대 42와 같은 숫자를 표시하도록 선택할 수 있나요?

type()으로 선택을 시도했지만 ip a s type ...실제로는 작동하지 않습니다.

답변1

각 정보를 별도의 줄에 출력하는 옵션이 있습니다 -o.

-o, -oneline
각 레코드를 한 줄에 출력하고 줄 바꿈을 "\" 문자로 바꿉니다. 이는 wc(1) 또는 grep(1) 출력을 사용하여 레코드 수를 계산하려는 경우 편리합니다.

그러면 ip -o a s up |sort -n작업이 완료됩니다. ip -o a s up |sort -n |tr '\\' '\n'필요한 경우 백슬래시를 다시 개행 문자로 변환할 수 있습니다.

옵션을 사용할 때 일부 정보가 손실되는 것 같습니다 -o(이유는 모르겠습니다). 그러면 sort 명령에 전달하기 전에 다음 awk 전처리 대안을 사용할 수 있습니다.

ip a s up \
| awk '{ printf "%s" (NR>1 && /^[0-9]+:/?"\0":(NR>1?"\n":"")) $0 }' \
| sort -nz \
| tr '\0' '\n'

즉, 각 인터페이스 블록 사이에 null 문자를 추가한 다음 sort with를 사용하여 -znull로 구분된 레코드의 입력을 정렬하고 마지막으로 sort with를 사용하여 이러한 null 문자를 개행 문자로 복원합니다 tr.

답변2

GNU awk 사용:

ip a s up | gawk '
  match($0, /^([0-9]+): /, m) {
    if (prev) ip[prev] = lines
    prev = m[1]
    lines = ""
  }
  { lines = lines $0 RS }
  END {
    if (prev) ip[prev] = lines
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (num in ip) print ip[num]
  }
'

관련 정보