LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 04-03-2008, 08:04 AM   #1
tallmtt
Member
 
Registered: Jun 2005
Location: Georgia, USA
Distribution: Arch, Gentoo, Ubuntu
Posts: 91

Rep: Reputation: 15
Help needed for using awk to parse a file to make array for bash script


I am trying to write a script that will run "iwlist <interface> scanning >> iwlist-file."

Then I want to parse the file so that the ESSID, AP, encryption key off vs on, and signal strength all become variables that I will be able to use in the script.

I will have some preferred networks with special static vs dhcp connections that if that ESSID is available, a different script will run (say in same directory named by network) but if no network is found, it would prioritize the available networks with Encryption key off by signal strength and connect automatically to it.

The file I need to parse to obtain those variables would look something like this:

Code:
BigDog tallmtt # iwlist ath0 scanning
ath0      Scan completed :
          Cell 01 - Address: 00:06:25:E7:29:5F
                    ESSID:"Home"
                    Mode:Master
                    Frequency:2.437 GHz (Channel 6)
                    Quality=38/70  Signal level=-57 dBm  Noise level=-95 dBm
                    Encryption key:off
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s
                    Extra:bcn_int=100
          Cell 02 - Address: 00:18:4D:92:D5:B6
                    ESSID:"NETGEAR"
                    Mode:Master
                    Frequency:2.462 GHz (Channel 11)
                    Quality=7/70  Signal level=-88 dBm  Noise level=-95 dBm
                    Encryption key:off
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 18 Mb/s
                              24 Mb/s; 36 Mb/s; 54 Mb/s; 6 Mb/s; 9 Mb/s
                              12 Mb/s; 48 Mb/s
                    Extra:bcn_int=100
          Cell 03 - Address: 00:1C:10:47:6E:50
                    ESSID:"linksys"
                    Mode:Master
                    Frequency:2.437 GHz (Channel 6)
                    Quality=11/70  Signal level=-84 dBm  Noise level=-95 dBm
                    Encryption key:on
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 18 Mb/s
                              24 Mb/s; 36 Mb/s; 54 Mb/s; 6 Mb/s; 9 Mb/s
                              12 Mb/s; 48 Mb/s
                    Extra:bcn_int=100
 
Old 04-03-2008, 09:20 AM   #2
anupamsr
Member
 
Registered: Sep 2004
Location: India
Distribution: Kubuntu, Archlinux, Suse, Gentoo, Mandrake
Posts: 370

Rep: Reputation: 30
Something like this:
Code:
$ ESSID=(`grep ESSID: filename|sed -e 's/ //g'|cut -c7-|xargs`)
$ echo $ESSID[1]
Home
 
Old 04-03-2008, 10:37 AM   #3
tallmtt
Member
 
Registered: Jun 2005
Location: Georgia, USA
Distribution: Arch, Gentoo, Ubuntu
Posts: 91

Original Poster
Rep: Reputation: 15
Thanks for your quick reply. That lists the available networks, but I want to be able to somehow associate the ESSID with its specific AP, key (off or on), and signal strength.

Maybe breaking up the file into separate temporary files in /tmp/ with that info? maybe awk array? I don't know how todo either and am quite a novice at scripting.

Thanks again for your help.
 
Old 04-03-2008, 11:39 AM   #4
unSpawn
Moderator
 
Registered: May 2001
Posts: 26,988
Blog Entries: 54

Rep: Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743
Probably way convoluted but with
Code:
#!/bin/sh
retVal() { case "${l[0]}" in Ce*) echo -en "${l[4]} ";; ES*|Fr*) echo -en "${l[0]//*:/} ";; 
Q*) echo -en "${l[0]//*=/} ";; Encry*) echo ${l[1]//*:/};; *) continue;; esac; }
iwlist ath0 scanning|awk '/(Cell|ESS|Freq|Qual|Encry)/ {print}'|while read line; do
l=(${line}); retVal; done; exit 0
you don't need a temp file, it gets you the output as space separated values on one line per AP, so you can pack that output per line in arrays to work on.
Here's some links to BaSH scripting guides: http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html, http://www.tldp.org/LDP/Bash-Beginne...tml/index.html (and http://www.tldp.org/LDP/abs/html/).
 
Old 04-03-2008, 11:53 AM   #5
anupamsr
Member
 
Registered: Sep 2004
Location: India
Distribution: Kubuntu, Archlinux, Suse, Gentoo, Mandrake
Posts: 370

Rep: Reputation: 30
I am blind.

May be one day I will have vision.
 
Old 04-03-2008, 12:33 PM   #6
unSpawn
Moderator
 
Registered: May 2001
Posts: 26,988
Blog Entries: 54

Rep: Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743Reputation: 2743
Quote:
Originally Posted by anupamsr View Post
I am blind.
Yeah, you're right. It's an abomination. This should look "better":
Code:
iwlist ath0 scanning| awk '/Cell/ {print $5}; /ESS/ {print substr($1,7)}; /Freq/ \
{print substr($1,11)}; /Qual/ {print substr($1,9)}; /Encr/ {print substr($2,5)}'
 
Old 04-03-2008, 01:15 PM   #7
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by unSpawn View Post
This should look "better"
How about this:
Code:
iwlist ath0 scanning | awk -F '[ :=]+' '/(ESS|Freq|Qual)/{ printf $3" " }
/Encr/{ print $4 }'
Of course if the ESSID is something like "My Encrypted AP" you are in trouble.

Last edited by osor; 04-03-2008 at 01:21 PM. Reason: Removed address since the OP doesn’t ask for it
 
Old 04-03-2008, 05:40 PM   #8
tallmtt
Member
 
Registered: Jun 2005
Location: Georgia, USA
Distribution: Arch, Gentoo, Ubuntu
Posts: 91

Original Poster
Rep: Reputation: 15
You all are great! This command outputs:
Code:
# iwlist ath0 scanning | awk -F '[ :=]+' '/(ESS|Freq|Qual)/{ printf $3" " } /Encr/{ print $4 }'

"Home" 2.437 39/70 off
"linksys" 2.437 12/70 on
"NETGEAR" 2.462 4/70 off
"linksys" 2.437 7/70 off
Can someone give me an explanation of the command?

Thanks for your help - this gives me the setup I need to make an associative array in awk.

My next step is to make each line a field in the array. I will work on this tomorrow and if I need help will post that as well.

Any suggestions are always welcome.

Last edited by tallmtt; 04-03-2008 at 09:21 PM.
 
Old 04-04-2008, 01:20 PM   #9
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by tallmtt View Post
Can someone give me an explanation of the command?
Yes. The first part (-F '[ :=]+') sets your “field separator” to be one or more space, colon, or equal sign characters. The first command (/(ESS|Freq|Qual)/{ printf $3" " }) says that whenever awk encounters either ESS, Freq, or Qual, it will print the third field followed by a space (with no newline). The second command (/Encr/{ print $4 }) says that when awk encounters Encry, it will print the fourth field, followed by a newline. The result is that you get the output you want. If you wanted additionally to have the address printed out, you could add the command
Code:
/Cell/{printf substr($0,30)" "}
which means to print the entire line after the character at index 30 when awk encounters Cell.
Quote:
Originally Posted by tallmtt View Post
Any suggestions are always welcome.
If all you need to do is sort the output, why not use the sort command. For example, suppose I had the following output:
Code:
# iwlist ath0 scanning | awk -F '[ :=]+' '/(ESS|Freq|Qual)/{ printf $3" " } /Encr/{ print $4 }'
"foo" 2.437 19/70 off
"bar" 2.437 9/70 on
"baz" 2.462 39/70 on
"qux" 2.437 56/70 off
"quux" 2.437 34/70 off
I want to sort this list first by the fourth field alphabetically (so off comes before on) and then by the third field numerically in descending order. So I could do:
Code:
# iwlist ath0 scanning | awk -F '[ :=]+' '/(ESS|Freq|Qual)/{ printf $3" " } /Encr/{ print $4 }' | sort -k4 -k3nr
"qux" 2.437 56/70 off
"quux" 2.437 34/70 off
"foo" 2.437 19/70 off
"baz" 2.462 39/70 on
"bar" 2.437 9/70 on
The above should work as long as the quality field is a fraction with denominator 70 (since sort only looks at the initial numerical part). If you want something that will be smart enough to tell that 70/100 is less than 69/70, you will probably want awk to print a decimal for you instead of the number itself.
 
Old 12-09-2008, 09:49 AM   #10
godzillarama
LQ Newbie
 
Registered: Dec 2008
Posts: 17

Rep: Reputation: 0
Hello. I found this older thread by searching via Google and it has been a great help to me as I learn scripting. However, I must be missing something, because I still don't see how these examples make the results available as variables. I'd like to take the results and put them into an Xdialog menu so that the user could select which network to connect to, then pass the results to the iwconfig command based on the user's selection. I find that if I use iwconfig, I can connect more reliably than via wicd or WiFi Radar, neither of which seem to work very well in my configuation.

I've purchased some books on bash scripting, but I'm at a wall on the variable array technique. I'd appreciate any advice.
 
Old 12-10-2008, 12:18 AM   #11
burschik
Member
 
Registered: Jul 2008
Posts: 159

Rep: Reputation: 31
Well, if you can print out the information you need, you can also put it into variables, for instance by using "read":
Code:
print whatever | while read var1 var2 ...; do whatever; done
 
Old 08-15-2009, 01:10 AM   #12
laho
LQ Newbie
 
Registered: May 2009
Distribution: Debian, Ubuntu
Posts: 10

Rep: Reputation: 0
I wish I searched for this thread instead of reinventing the wheel which took me weeks while holding a crying newborn. But it was great to learn the basics of awk and grep.

I am a recent migrant from Windows where I was using Netstumbler to align high gain antennas. I haven't found a simple tool in Linux that could provide a graphical feedback of signal level so I set to make my own script for this. I just need some direction, not asking anyone to write this for me.

For illustration the on-screen feedback would look something like this:

"MyWireless" 00:21:1E:41:E9:50 Channel:6 Signal Level -59 on
===================================================================

"Hotspot" 00:21:1E:41:E9:40 Channel:6 Signal Level -70 off
========================
...

The idea came from Wavemon except this one would show all non-associated APs.

I figured out how to make an animated bar and how to parse the output of 'iwlist scanning' and get the numerical values I need.

I am having trouble separating the iwlist output's cells so I can feed one number at a time to the part of the script that's doing the graphical bar feedback.

For example:
Code:
# extract Signal Level
iwlist wlan0 scanning | awk -F= '/Quality/ {print substr($3,1,3)}'
will return Signal Level values for all ESSIDs available at the given moment. But I need to filter them by the Address value so I can send only one number to be echoed as an animated bar (or histogram).

I haven't studied in detail how 'iwlist scanning' sorts out the cell output. They are not sorted by signal quality, level, etc. I am guessing that the order of cells may vary so simply filtering the output of the above code based on the order may not work. I think the solution I need has to be contained within the original awk line and tied to a unique identifier like Address.

Any tips are much appreciatted. What an amazing flexibility in Linux. I wish I had more time to play.
 
Old 04-14-2012, 01:16 PM   #13
de55
LQ Newbie
 
Registered: Apr 2012
Posts: 1

Rep: Reputation: Disabled
Thanx for the oneliner, osor, the best approach I've found so far.

But, in my case, it outputs something like:

Code:
2.437 19/70 off
"foo" 2.437 9/70 on
"bar" 2.462 39/70 on
"baz" 2.437 56/70 off
"qux" 2.437 34/70 off
"quux"
So I came up with this (no problem with SSIDs with spaces, BSSIDs also printed):

Code:
iwlist ath0 scanning | awk -F '[ :=]+' '/Ad/{printf substr($0,30)" "} /(Channel:|Qual)/{printf $3" "} /Encr/{printf $4" "} /ESS/{print substr($0,27)}'
Not much experience with awk, would be nice to reorder fields, but without garbling oneliner...
 
  


Reply

Tags
bash, gentoo, iwconfig, iwlist, wireless


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Bash script, read file into array (Newbie) TheMeeks Programming 6 04-17-2007 08:20 AM
Bash script - how to reassemble file from array sixerjman Programming 11 08-25-2006 11:45 AM
ssimple shell script to parse a file ~sed or awk stevie_velvet Programming 7 07-14-2006 03:41 AM
bash script help to parse out text slack guy Linux - Newbie 3 12-30-2004 08:42 AM
Need help with perl/bash script to parse PicBasic file cmfarley19 Programming 13 11-18-2004 05:06 PM


All times are GMT -5. The time now is 01:11 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration