Iw wlan0 output analysis

I wrote a wlan manager script to work with open / ad-hoc / wep / wpa2 networks. Now I am trying to parse the output of iw wlan0 to get a good scan function for my script. My goal is to get the output as follows:

SSID channel signal encryption wlan-ap 6 70% wpa2-psk test 1 55% wep 

What I have already achieved is already output as follows:

 $ iw wlan0 scan | grep 'SSID\|freq\|signal\|capability' | tac SSID: Koti783 signal: -82.00 dBm capability: ESS Privacy ShortPreamble SpectrumMgmt ShortSlotTime (0x0531) freq: 2437 

I tried to learn bash / sed / awk, but havent found another way to get what I'm trying. So what's good for this?

+6
source share
5 answers

Here is my final solution based on Sudo_O answer :

 $1 == "BSS" { MAC = $2 wifi[MAC]["enc"] = "Open" } $1 == "SSID:" { wifi[MAC]["SSID"] = $2 } $1 == "freq:" { wifi[MAC]["freq"] = $NF } $1 == "signal:" { wifi[MAC]["sig"] = $2 " " $3 } $1 == "WPA:" { wifi[MAC]["enc"] = "WPA" } $1 == "WEP:" { wifi[MAC]["enc"] = "WEP" } END { printf "%s\t\t%s\t%s\t\t%s\n","SSID","Frequency","Signal","Encryption" for (w in wifi) { printf "%s\t\t%s\t\t%s\t%s\n",wifi[w]["SSID"],wifi[w]["freq"],wifi[w]["sig"],wifi[w]["enc"] } }' 

Output:

 $ sudo iw wlan0 scan | awk -f scan.awk SSID Frequency Signal Encryption netti 2437 -31.00 dBm Open Koti783 2437 -84.00 dBm WPA WLAN-AP 2462 -85.00 dBm WPA 
+7
source

The following is a GNU awk script that captures the SSID and channel for each unique BSS:

 /^BSS / { MAC = $2 } /SSID/ { wifi[MAC]["SSID"] = $2 } /primary channel/ { wifi[MAC]["channel"] = $NF } # Insert new block here END { printf "%s\t\t%s\n","SSID","channel" for (w in wifi) { printf "%s\t\t%s\n",wifi[w]["SSID"],wifi[w]["channel"] } } 

It should be easy for you to add new blocks for signal and encryption, given all the research you have done.

Save the script to a file, for example wifi.awk , and run it as:

 $ sudo iw wlan0 scan | awk -f wifi.awk 

The output will be in the programmed format:

 SSID channel wlan-ap 6 test 1 
+5
source

Here is a simple Bash function that uses only Bash internals and spawns only one sub-shell:

 #!/bin/bash function iwScan() { # disable globbing to avoid surprises set -o noglob # make temporary variables local to our function local AP S # read stdin of the function into AP variable while read -r AP; do ## print lines only containing needed fields [[ "${AP//'SSID: '*}" == '' ]] && printf '%b' "${AP/'SSID: '}\n" [[ "${AP//'signal: '*}" == '' ]] && ( S=( ${AP/'signal: '} ); printf '%b' "${S[0]},";) done set +o noglob } iwScan <<< "$(iw wlan0 scan)" 

Output:

 -66.00,FRITZ!Box 7312 -56.00,ALICE-WLAN01 -78.00,o2-WLAN93 -78.00,EasyBox-7A2302 -62.00,dlink -74.00,EasyBox-59DF56 -76.00,BELAYS_Network -82.00,o2-WLAN20 -82.00,BPPvM 

The function can be easily modified to provide additional fields by adding the necessary filter while reading -r AP while-loop, for example:

 [[ "${AP//'last seen: '*}" == '' ]] && ( S=( ${AP/'last seen: '} ); printf '%b' "${S[0]},";) 

Output:

 -64.00,1000,FRITZ!Box 7312 -54.00,492,ALICE-WLAN01 -76.00,2588,o2-WLAN93 -78.00,652,LN8-Gast -72.00,2916,WHITE-BOX -66.00,288,ALICE-WLAN -78.00,800,EasyBox-59DF56 -80.00,720,EasyBox-7A2302 -84.00,596,ALICE-WLAN08 
+3
source

All in all, it is bad practice to try to parse the complex output of programs designed for people to read (rather than parsing machines).

eg. iw output may change depending on the language settings of the system and / or iw version, leaving you with a β€œmanager” that only works on your development machine.

instead, you can use the same interface that iw uses to get information: the backend libnl library

you may also need to look at the wireless-tools ( iwconfig , iwlist , ...) that use libiw .

+2
source

I use this solution for openwrt:

wlan_scan.sh

 #!/bin/sh sudo iw dev wlan0 scan | awk -f wlan_scan.awk | sort 

wlan_scan.awk

 /^BSS/ { mac = gensub ( /^BSS[[:space:]]*([0-9a-fA-F:]+).*?$/, "\\1", "g", $0 ); } /^[[:space:]]*signal:/ { signal = gensub ( /^[[:space:]]*signal:[[:space:]]*(\-?[0-9.]+).*?$/, "\\1", "g", $0 ); } /^[[:space:]]*SSID:/ { ssid = gensub ( /^[[:space:]]*SSID:[[:space:]]*([^\n]*).*?$/, "\\1", "g", $0 ); printf ( "%s %s %s\n", signal, mac, ssid ); } 

result

 -62.00 c8:64:c7:54:d9:05 a -72.00 70:72:3c:1c:af:17 b -81.00 78:f5:fd:be:33:cb c 
+2
source

Source: https://habr.com/ru/post/950076/


All Articles