2

I currently have the following code which nicely outputs some information about the wireless networks around me:

sudo iw wlan0 scan | sed -nr '/SSID: |signal: |primary channel: /p' | sed 's/^[\t]*//g' | sed 's/^SSID: //' | sed 's/signal: / * signal: /'

(Please forgive me if that is unnecessarily long and/or generally messy code). Which outputs something along the lines of this:

 * signal: -61.00 dBm
<network 1 name>
 * primary channel: 10
 * signal: -37.00 dBm
<network 2 name>
 * primary channel: 1
 * signal: -80.00 dBm
<network 3 name>
 * primary channel: 11
 * signal: -90.00 dBm
<network 4 name>
 * primary channel: 11

However, due to the original formatting of the iw wlan0 scan command, the signal strength of each network is printed before the actual network name. What I would like is for the result to be:

<network 1 name>
 * signal: -61.00 dBm
 * primary channel: 10
<network 2 name>
 * signal: -37.00 dBm
 * primary channel: 1
<network 3 name>
 * signal: -80.00 dBm
 * primary channel: 11
<network 4 name>
 * signal: -90.00 dBm
 * primary channel: 11

How can I achieve this output? I was thinking I could somehow search for the pattern * signal: and then swap that line with the next line, but I have no idea how to implement this.

(If possible I would like something that could be appended to the end of my command, for example another sed command. Otherwise I am open to any solutions within bash)

EDIT: where above I have said <network # name>, that was just me removing some names on networks around me, and represents actual network names that will be there. Basically the lines with the network names will contain only the network's name, not '<' or '>' or anything else.

3 Answers 3

2

Try this with GNU sed:

sed -ne '/signal:/{h;b};/^[^ ]/{p;x};p' file

See: man sed

3
  • Oh sorry! I forgot to add that <network # name> just represents the name of the network that will be there, so the script will not know beforehand what the names on the networks will be.
    – user106579
    Commented Mar 14, 2015 at 11:56
  • Okay, I've updated my answer. I assume that your network name does not begin with a space.
    – Cyrus
    Commented Mar 14, 2015 at 12:03
  • 1
    What is this supposed to do exactly? Is it intended as a filter to be run after the asker's own sed like iw | sed 'askers script' | sed 'your script'? If so then why not just fix the asker's script? What file?
    – mikeserv
    Commented Jul 21, 2015 at 3:11
1

I recommend running iw --help and reading the last line of output.


That aside, I think you could do without all those pipes and use a single sed invocation:

iw wlan0 scan | sed -n '/signal:/{s/^[[:blank:]]*/ * /;h}
/^[[:blank:]]*SSID: /{s///;G;p};/primary/{s/^[[:blank:]]*/ /;p}'

i.e.:

/signal:/{s/^[[:blank:]]*/ * /;h} - format signal line and copy over the hold space
/^[[:blank:]]*SSID: /{s///;G;p} - format SSID line, appendinG the line from the hold space to pattern space and print
/primary/{s/^[[:blank:]]*/ /;p} - format primary line and print it

1

On my computer doing...

sudo iw wlp0s18f2u1 scan |
sed -Ee:n -e'$!N;/^.sig/!D' \
          -e'/\* pri/s/.([^\t]*\t).*(SSID:[^\t]*\t).*p/\2\1p/;t' \
          -ebn

...gets results like...

SSID: ATT477A7i6
    signal: -61.00 dBm
    primary channel: 6
SSID: ATT5K5I6b4
    signal: -65.00 dBm
    primary channel: 6
SSID: ATT960
    signal: -75.00 dBm
    primary channel: 6
SSID: Bernardo Shores WiFi 4
    signal: -77.00 dBm
    primary channel: 6

It works with a GNU sed. A more portable version might look like:

(   t=$(printf \\t) nt=[\^$t]*$t
    sudo iw wlp0s18f2u1 scan |
    sed -e:n -e'$!N;/^.sig/!D' \
             -e"/* pri/s/.\($nt\).*\(SSID:$nt\).*p/\2\1p/;t" \
             -ebn
)

You must log in to answer this question.