5

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')
9
  • what about awk -F'\t'?
    – jesse_b
    Oct 19, 2017 at 19:02
  • @Jesse_b just tried it now and didn't work Oct 19, 2017 at 19:04
  • it's not clear. what do you want to put in the networks and bars variables? in the booth case I typed awk command without '-F' option : I've got the list of the networks and the db of the signal.
    – dubis
    Oct 19, 2017 at 19:14
  • 2
    At least with recent versions of nmcli, you can avoid needing to parse the output by specifying exactly what fields you want (and in what order) e.g. networks=$(nmcli -t -f ssid dev wifi). There's also an option to print in a machine-parsable mode. Oct 19, 2017 at 19:15
  • 2
    In that case you should (IMHO) almost certainly using the --mode multiline format if your version of nmcli supports it - which gives you colon-delimited key-value pairs out of the box Oct 19, 2017 at 19:40

2 Answers 2

11
awk -F' {2,}' # means - two or more spaces.

or

awk -F'  +' # means - one space, then one or more spaces.

This commands mean the same - use 2 or more spaces as fields delimiter.

3

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .