Awk – Delimit by Space Greater Than 1

awksedtext processing

I'm trying to parse the results of nmcli dev wifi which produces a result like this:

*  SSID                 MODE   CHAN  RATE       SIGNAL  BARS  SECURITY  
   Prk                  Infra  11    54 Mbit/s  99      ▂▄▆█            
   VIDEOTRON2255        Infra  11    54 Mbit/s  67      ▂▄▆_  WPA1 WPA2 
   a space              Infra  6     54 Mbit/s  65      ▂▄▆_  WPA2      
*  TNCAP4D0B18          Infra  11    54 Mbit/s  52      ▂▄__            

Initially I was just parsing using awk -F" " which worked for almost all cases. I'm finding any wifi network with a space in it throws this off completely.

So I instead try using two spaces instead of one this didn't produce the results I expected. How can I consistently parse the columns in the above output?

Current script is something like this:

nmcli dev wifi | sed 's/\*//g' > /tmp/scan
networks=$(cat /tmp/scan | awk -F"  " '{print $1}' | sed '1d')
# ...
bars=$(cat /tmp/scan | awk -F"  " '{print $6}' | sed '1d')

Best Answer

Parse the first line to find at which position each column starts, then parse the other lines based on column numbers. For example, the following script prints column 2 which is the SSID.

nmcli_output=$(nmcli dev wifi)
printf %s\\n "$nmcli_output" | awk -v column=2 '
    NR==1 {
        i=1; p=1;
        while(match($0,/^[^ ]+ +/)) {
            a[i++] = p;
            p += RLENGTH;
            $0 = substr($0, RLENGTH+1);
        }
    }
    NR!=1 {
        text = substr($0, a[column], a[column+1] ? a[column+1]-a[column] : length);
        sub(text, / +$/, "");
        print text
    }'

Depending on what you want to do, calling awk multiple times may not be the best solution. Keep in mind that you can run shell commands from awk with the system function.

Related Question