Parsing file with AWK or SED - Help needed


cube48

Member
Joined
Oct 6, 2008
Messages
288
Location
Bohemia
Website
www.48.cz
I'm writting a script for automatized bluetooth GPS connection. I even have working PND but one thing is not as elegant as it could be.


Official GPS guide suggests insertion of BT MAC address into /etc/bluetooth/rfcomm.conf. My script is currently reading the MAC address from txt file in appdata where it must be inserted manually too. Which is unnecessary redundancy.


I would like to read rfcomm.conf and parse the GPS MAC address out of it.


Unfortunatelly my AWK or SED skills are close to zero. I used AWK long, long time ago on a very basic level. Of course I tried to search the internet for help but all I found was focused on parsing XML and not really fitting my case.


This is how simple rfcomm.conf looks like:



Code:
# RFCOMM configuration file.


rfcomm0 {

# Automatically bind the device at startup

	bind no;


	# Bluetooth address of the device

	device XX:XX:XX:XX:XX:XX;


	# RFCOMM channel for the connection

	channel	1;


	# Description of the connection

	comment "GPS";

}


Goal is to find the right rfcomm# element - the one which contains line "comment "GPS";" - and then read the MAC value from line "device XX:XX:XX:XX:XX:XX;" .


Keep in mind that users can have more rfcomm# devices defined in this file.


Thanks in advance for any help!
 
I'm neither an AWK nor a SED expert, will a quick-and-dirty python script do?



Code:
#!/usr/bin/python


import re

import sys


regexp = '{[^}]*device (..:..:..:..:..:..);[^}]*comment "GPS";[^}]*}'

with open(sys.argv[1]) as f:

    content = f.read().replace('\n', '')


print re.search(regexp, content).group(1)

Pass the file to parse as parameter to this script.
 
Last edited by a moderator:
Code:
regexp = 'device (..:..:..:..:..:..);.*?comment "GPS";.*?}'
Sorry, but this wont work as expected : ".*" match anything, and the regexp rule say : match first occurence. So the regexp will match the first "device (..:..:..:..:..:..);" then the first "comment "GPS";" no matter if the device and the comment are part of the same group....

you could exclude "}" caracter in the middle .* like [^\}]* to make it work.



You could also probably write this as a sed command but as I like (thomas)awk, here is my version (like Caine's one quick-and-dirty which might contain some flaw) :



Code:
awk 'BEGIN{r="";f=0}END{if(f==1)print r}/^rfcomm/&&(f==0||r==""){f=0;r=""}/device.*;/&&r==""{r=$2}/comment/&&/GPS/{f=1}' < /etc/bluetooth/rfcomm.conf


Sure that's way less readable than caine version ;)
 
Yeah, you're right. I had [^}]* there at first, but depending on the actual contents of the file it may or may not work.


Should have tested on a file with multiple entries. Should be fixed now.
 
Last edited by a moderator:
Oh I didnt knew about greedy/non-greedy in regex.


Thanks for the lesson ;)
You were still right though. It would match the first element and then happily continue scanning for a comment="GPS" in a non-greedy fashion (and locate a match in another block).


[edit]Too many edits...this thread reads awkward now ;p [/edit]
 
Last edited by a moderator:
Code:
regexp = 'device (..:..:..:..:..:..);.*?comment "GPS";.*?}'
I notice my original error now. This should be:



Code:
'.*device (..:..:..:..:..:..);.*?comment "GPS";.*?}'

By omitting the .* at the beginning, I selected the first device followed by a comment "GPS", I should select the last device followed by comment "GPS" instead. Nevertheless, it's safer to enforce that they occur in the same block like it is now.


I'm always too hasty when writing regular expressions and it never goes right the first time :p
 
You could also probably write this as a sed command but as I like (thomas)awk, here is my version (like Caine's one quick-and-dirty which might contain some flaw) :



Code:
awk 'BEGIN{r="";f=0}END{if(f==1)print r}/^rfcomm/&&(f==0||r==""){f=0;r=""}/device.*;/&&r==""{r=$2}/comment/&&/GPS/{f=1}' < /etc/bluetooth/rfcomm.conf

That's exactly what I was looking for! Thanks! Could you please amend it to remove ";" at the end of address? (If I read it correctly, it is about removing last char from $2 in {r=$2} part?)
 
That's exactly what I was looking for! Thanks! Could you please amend it to remove ";" at the end of address? (If I read it correctly, it is about removing last char from $2 in {r=$2} part?)
yes, you got it right ;)



Code:
awk 'BEGIN{r="";f=0}END{if(f==1)print  r}/^rfcomm/&&(f==0||r==""){f=0;r=""}/device.*;/&&r==""{r=substr($2,1,length($2)-1)}/comment/&&/GPS/{f=1}'  < /etc/bluetooth/rfcomm.conf

better ?
 
Code:
awk 'BEGIN{r="";f=0}END{if(f==1)print  r}/^rfcomm/&&(f==0||r==""){f=0;r=""}/device.*;/&&r==""{r=substr($2,1,length($2)-1)}/comment/&&/GPS/{f=1}'  < /etc/bluetooth/rfcomm.conf

better ?

Perfect! Thank you both guys!


I just reviewed my script and ...er ... I will also need to pull out the GPS rfcomm# in separate awk query (in example above the output should be "rfcomm0"). Can I bother you again? I hope it's the last thing, I promise :)
 
I just reviewed my script and ...er ... I will also need to pull out the GPS rfcomm# in separate awk query (in example above the output should be "rfcomm0"). Can I bother you again? I hope it's the last thing, I promise :)
guessing you still need the GPS one :



Code:
awk 'BEGIN{r=""}/^rfcomm/{r=$1}/comment/&&/GPS/{print r;exit}' < /etc/bluetooth/rfcomm.conf
 
Back
Top