AWK는 특정 문자열을 추출하는 동안 출력 라인을 연결합니다.

AWK는 특정 문자열을 추출하는 동안 출력 라인을 연결합니다.

서브넷에 대한 nmap의 출력을 고려하면

Nmap scan report for 192.168.1.20
Host is up (0.010s latency).
MAC Address: EC:13:B2:E2:20:48 (Netonix)
Nmap scan report for 192.168.1.21
Host is up (0.010s latency).
MAC Address: EC:13:B2:E2:13:68 (Netonix)
Nmap scan report for 192.168.1.23
Host is up (0.010s latency).
MAC Address: EC:13:B2:E1:AE:A8 (Netonix)
Nmap scan report for 192.168.1.99
Host is up (0.00076s latency).
MAC Address: 90:6C:AC:48:86:DA (Fortinet)

목표는 csv 또는 기타 구분된 형식으로 출력을 얻는 것입니다.

IP,MAC,RTT
192.168.1.20,EC:13:B2:E2:20:48,0.010s
192.168.1.21,EC:13:B2:E2:13:68,0.010s
...

위의 작업은 AWK를 사용하여 2단계 프로세스로 수행되었습니다.

$time_date=$(date "+%Y-%m-%d_%T")    # Get the immediate date and time
$nmap_command=$(nmap -sP 192.168.1.0/24 -n --max-rtt-timeout 50ms)

# Concatenate all lines including and between the patterns "Nmap scan report for"
c_list=$((awk '/Starting|done:/ {next} /Nmap scan report for/{ if (x) print x; x=""; }{ x=(!x)?$0:x" "$0; }END{ print x; }')<<<$nmap_command)

# Extract the values of interest from each line, add a header line, then add delimiter for every value extracted
list=$((awk -v OFS=',' -v date=$time_date 'BEGIN{ print "Date,IP,MAC,RTT" };{ gsub(/[()]/,""); for (I=1;I<=NF;I++) if ($I == "for") ip=$(I+1); else if ($I == "up") lat=$(I+1); else if ($I == "Address:") mac=$(I+1); } { print date, ip, mac, lat }')<<<$c_list)

printf '%s\n' "$list" > ~/Desktop/list.csv  # Send output to file

exit 0

문제는 위의 2단계 awk 프로세스를 하나의 awk 명령으로 결합할 수 있나요? 미리 제공해 주신 모든 정보에 감사드립니다.

편집하다 몇 가지 변형을 통해 이 두 단계를 강화해 보세요.

x_list=$((awk '/Starting|done:/ {next} /Nmap scan report for/{ if (x) print x; x=""; }{ x=(!x)?$0:x" "$0; }END I=x BEGIN{ print "Date,IP,MAC,RTT" };{ gsub(/[()]/,""); for (I=1;I<=NF;I++) if ($I == "for") ip=$(I+1); else if ($I == "up") lat=$(I+1); else if ($I == "Address:") mac=$(I+1); } { print date, ip, mac, lat }')<<<$list_ips)

전망은 밝지 않습니다. AWK는 항상 END와 BEGIN 사이의 간격에서 처리를 중지하는 타당한 이유를 제공합니다. 이 연습은 실제로 모든 데이터를 반복 패턴으로 렌더링할 수 있는 (bash) 함수를 생성하려는 시도이며, nmap 출력은 단지 예일 뿐입니다.

답변1

일반적인 접근 방식은 모든 행의 필수 정보를 awk 변수에 저장한 다음 블록의 마지막 행에서 데이터를 인쇄하는 것입니다. 따라서 예를 들어 다음과 같은 내용이 있을 것입니다(예제 데이터에 표시되지 않기 때문에 호스트 종료 지연 사례를 코딩하지 않았습니다).

nmap -sP 192.168.1.0/24 -n --max-rtt-timeout 50ms |
  awk '/Nmap scan report for / {ip=$5}
       /Host is up/ { latency=$4 ; sub(/(/,"",latency) }
       /MAC Address: / { mac=$3; print(ip "," mac "," latency) ; ip=mac=latency="unknown" }
       BEGIN { print "IP,MAC,RTT"}

데이터가 항상 완전한지 여부에 따라 블록의 마지막 줄에서 변수를 지우는 것이 필요할 수도 있고 필요하지 않을 수도 있습니다. 변수가 많은 경우 ip와 같은 스칼라 변수 대신 배열을 사용하는 것이 좋습니다. 이러한 변수는 한 번의 삭제로 모두 지워질 수 있기 mac때문입니다 .latency

관련 정보