Bring $VARIABLE into sed

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Post Reply
Message
Author
User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

Bring $VARIABLE into sed

#1 Post by greengeek »

I am trying to write a utility that will allow me to modify the .asoundrc file that is used by the bt4stretch code in the Debian Live starter kit from rcrsn51.

I need to "swap in" new "BT MAC address" values so that Alsa will direct the bluetooth stream to whichever device I want.

There is probably an awk, grep or sed one liner that will do what I need, but at this stage i am trying to go step by step and learn as I go.

When the file is in it's original state the BT_MAC_address is in it's generic form ie: XX:XX:XX:XX:XX:XX and the user needs to manually change it to match the desired output device.
(see /root/.asoundrc file contents at bottom of post)

I can use sed to replace the generic MAC as follows:

Code: Select all

sed 's/\(.*\)"XX:XX:XX:XX:XX:XX"/\1"F2:FA:91:DD:FA:C6"/' asoundrc.txt > asoundrcTMP.txt
However, this is not useful to swap to other BT devices - only useful when the file is in it's original state, so I need to identify the BT_MAC_address some other way.

I tried using awk to identify the field that occurs after the "second occurrence of string: 'device' " as follows:

Code: Select all

OLDBTMAC= awk '$1=="device" {print $2}' /root/asoundrc.txt
echo $OLDBTMAC
This seemed to work ok and returned the string "XX:XX:XX:XX:XX:XX" so I tried to use the $OLDBTMAC variable in a sed example:

Code: Select all

sed 's/\(.*\)`$OLDBTMAC`/\1"F2:FA:91:DD:FA:C6"/' asoundrc.txt > asoundrcTMP.txt
but all that did is to write the original file into the "TMP" file unchanged.

I tried various ways to "escape" the $OLDBTMAC but could not hit the sweet spot.

Any ideas what I have to do to bring a variable into sed?

Here are the original contents of the default /root/.asoundrc file:

Code: Select all

### these three lines enable the regular sound card ###

defaults.pcm.card 0
defaults.pcm.device 0
defaults.ctl.card 0

##################

ctl.equal {
 type equal;
}

pcm.plugequal {
  type equal;
  slave.pcm "plughw:0,0";
}

pcm.equal{
  type plug;
  slave.pcm plugequal;
}

### these two lines enable the equalizer ###

#pcm.!default pcm.equal
#ctl.!default ctl.equal

################

pcm.bluetooth {
	type plug
	slave.pcm {
		type bluealsa
		interface "hci0"
		device "XX:XX:XX:XX:XX:XX"
		profile "a2dp"
	}
}

ctl.bluetooth {
 type bluealsa
}

### these two lines enable bluetooth ###

pcm.!default pcm.bluetooth
ctl.!default ctl.bluetooth

User avatar
flea
Posts: 5
Joined: Mon 13 Aug 2018, 17:33
Location: Minnesota, USA

#2 Post by flea »

Try replacing the back-ticks with single quotes, something like:

Code: Select all

sed 's/\(.*\)'$OLDBTMAC'/\1"F2:FA:91:DD:FA:C6"/' asoundrc.txt > asoundrcTMP.txt

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

#3 Post by greengeek »

flea wrote:Try replacing the back-ticks with single quotes, something like:

Code: Select all

sed 's/\(.*\)'$OLDBTMAC'/\1"F2:FA:91:DD:FA:C6"/' asoundrc.txt > asoundrcTMP.txt
Thanks. Unfortunately that has an interesting but unsatisfactory result :-)

Code: Select all

### these three lines enable the regular sound card ###"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
defaults.pcm.card 0"F2:FA:91:DD:FA:C6"
defaults.pcm.device 0"F2:FA:91:DD:FA:C6"
defaults.ctl.card 0"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
##################"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
ctl.equal {"F2:FA:91:DD:FA:C6"
 type equal;"F2:FA:91:DD:FA:C6"
}"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
pcm.plugequal {"F2:FA:91:DD:FA:C6"
  type equal;"F2:FA:91:DD:FA:C6"
  slave.pcm "plughw:0,0";"F2:FA:91:DD:FA:C6"
}"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
pcm.equal{"F2:FA:91:DD:FA:C6"
  type plug;"F2:FA:91:DD:FA:C6"
  slave.pcm plugequal;"F2:FA:91:DD:FA:C6"
}"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
### these two lines enable the equalizer ###"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
#pcm.!default pcm.equal"F2:FA:91:DD:FA:C6"
#ctl.!default ctl.equal"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
################"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
pcm.bluetooth {"F2:FA:91:DD:FA:C6"
	type plug"F2:FA:91:DD:FA:C6"
	slave.pcm {"F2:FA:91:DD:FA:C6"
		type bluealsa"F2:FA:91:DD:FA:C6"
		interface "hci0""F2:FA:91:DD:FA:C6"
		device "XX:XX:XX:XX:XX:XX""F2:FA:91:DD:FA:C6"
		profile "a2dp""F2:FA:91:DD:FA:C6"
	}"F2:FA:91:DD:FA:C6"
}"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
ctl.bluetooth {"F2:FA:91:DD:FA:C6"
 type bluealsa"F2:FA:91:DD:FA:C6"
}"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
### these two lines enable bluetooth ###"F2:FA:91:DD:FA:C6"
"F2:FA:91:DD:FA:C6"
pcm.!default pcm.bluetooth"F2:FA:91:DD:FA:C6"
ctl.!default ctl.bluetooth"F2:FA:91:DD:FA:C6"

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

Re: Bring $VARIABLE into sed

#4 Post by MochiMoppel »

greengeek wrote:I tried using awk to identify the field that occurs after the "second occurrence of string: 'device' " as follows:

Code: Select all

OLDBTMAC= awk '$1=="device" {print $2}' /root/asoundrc.txt
echo $OLDBTMAC
This seemed to work ok and returned the string "XX:XX:XX:XX:XX:XX"
:shock: Indeed "seems" to work but doesn't.
What returns the string "XX:XX:XX:XX:XX:XX" is the awk statement.
The echo statement returns nothing (well, it returns a new line :lol: ) as you assign nothing to $OLDBTMAC, and with $OLDBTMAC being empty this explains your "interesting" result.

With a correct variable assignment flea's solution works perfectly.
Try

Code: Select all

OLDBTMAC=$(awk '$1=="device" {print $2}' /root/asoundrc.txt)

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

Re: Bring $VARIABLE into sed

#5 Post by greengeek »

MochiMoppel wrote:What returns the string "XX:XX:XX:XX:XX:XX" is the awk statement.
The echo statement returns nothing (well, it returns a new line :lol: ) as you assign nothing to $OLDBTMAC, and with $OLDBTMAC being empty this explains your "interesting" result.
Aahhh, thank you. I stumbled at the first hurdle, never mind the second.

That information lets me extract the variable correctly, so now I can go on to strip the first and last characters (") and substitute other BT address values.

Thanks to you both!

Code: Select all

#! /bin/bash

OLDBTMAC=$(awk '$1=="device" {print $2}' /root/asoundrc.txt)
echo $OLDBTMAC

OLDBTMACTRUNC=$(echo -n $OLDBTMAC | tail -c +2 | head -c -1)
echo $OLDBTMACTRUNC

sed 's/'$OLDBTMACTRUNC'/AA:BB:CC:DD:EE:FF/g' asoundrc.txt > asoundrc.TMP.txt
echo $OLDBTMACTRUNC
EDIT : I am now much closer to my goal:
(simplified the sed line too)

Code: Select all

#! /bin/bash

echo -n "Enter the new BT MAC address: " 
read NEWBTMAC
echo $NEWBTMAC

OLDBTMAC=$(awk '$1=="device" {print $2}' /root/asoundrc.txt)

OLDBTMACTRUNC=$(echo -n $OLDBTMAC | tail -c +2 | head -c -1)
echo "Old BT MAC address was $OLDBTMACTRUNC"

sed 's/'$OLDBTMACTRUNC'/'$NEWBTMAC'/g' asoundrc.txt > asoundrc.TMP.txt
echo "New BT MAC address is $NEWBTMAC"

Code: Select all

# ./echo4
Enter the new BT MAC address: AA:BB:CC:DD:EE:FF
AA:BB:CC:DD:EE:FF
Old BT MAC address was XX:XX:XX:XX:XX:XX
New BT MAC address is AA:BB:CC:DD:EE:FF
# 

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

Re: Bring $VARIABLE into sed

#6 Post by MochiMoppel »

greengeek wrote:That information lets me extract the variable correctly, so now I can go on to strip the first and last characters (") and substitute other BT address values.

Code: Select all

OLDBTMAC=$(awk '$1=="device" {print $2}' /root/asoundrc.txt)
echo $OLDBTMAC

OLDBTMACTRUNC=$(echo -n $OLDBTMAC | tail -c +2 | head -c -1)
echo $OLDBTMACTRUNC
I was curious if stripping the double quotes from the 2nd field of line

Code: Select all

      device "XX:XX:XX:XX:XX:XX"
could be done by the same awk statement since awk is pretty powerful.
Nothing wrong with your solution. Your's is one of many ways but I thought that this was a good opportunity for me to learn more about awk. After all stripping quotes is a very common task and knowing new tricks can't hurt.

Well, I nearly pulled my hair out yesterday. Nothing worked.
A new day, a good coffee, and now I think I cracked the nut:

Code: Select all

OLDBTMACTRUNC=$(awk '$1=="device" { gsub(""","",$2) ; print $2}' /root/asoundrc.txt)
echo $OLDBTMACTRUNC
Finds line with "device" in first field, then just for this line replaces all double quotes found in the 2nd field with nothing (i.e. deletes them) and finally prints this 2nd field.

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

Re: Bring $VARIABLE into sed

#7 Post by greengeek »

MochiMoppel wrote:I was curious if stripping the double quotes from the 2nd field ...could be done by the same awk statement since awk is pretty powerful.
I think I cracked the nut:

Code: Select all

OLDBTMACTRUNC=$(awk '$1=="device" { gsub(""","",$2) ; print $2}' /root/asoundrc.txt)
echo $OLDBTMACTRUNC
Finds line with "device" in first field, then just for this line replaces all double quotes found in the 2nd field with nothing (i.e. deletes them) and finally prints this 2nd field.
Excellent, thanks.
I am torn between finding code that is powerful and quick (ie: one liners such as yours) and code that divides functions into individual somewhat verbose steps that I can add comments to for the purposes of assisting later understanding. It's hard to know which way to go sometimes.

User avatar
flea
Posts: 5
Joined: Mon 13 Aug 2018, 17:33
Location: Minnesota, USA

Re: Bring $VARIABLE into sed

#8 Post by flea »

greengeek wrote:I am torn between finding code that is powerful and quick (ie: one liners such as yours) and code that divides functions into individual somewhat verbose steps that I can add comments to for the purposes of assisting later understanding. It's hard to know which way to go sometimes.
There's nothing wrong with using wicked one-liners so long as you thoroughly comment the code. As always with programming, it's application specific. Sometimes it's better to use a step-by-step coding method, and sometimes it's desirable to use a combobulated one-liner. It all depends on the result. If a one-liner gives a better result, then use it. If the step-by-step gives an equal result, then that's probably the better route if you're sharing the code. In the end, as the programmer, ultimately that's your call. If you need speed, and the one-liner does that, then that's what you want. If not, then maybe the step-by-step is what you need. That's where the creativity of the person doing the coding comes in.

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

#9 Post by greengeek »

That raises a question - is execution of code slowed down by the addition of comments? Obviously verbose notation increases the overall load time into RAM by increasing the size of a script - but does it also slow down the execution of the script itself?

User avatar
flea
Posts: 5
Joined: Mon 13 Aug 2018, 17:33
Location: Minnesota, USA

#10 Post by flea »

In theory, if you were to include a gazillion characterrs of comments, then yes. In practice, adding a few hundred characters are going to be negligible at best. If in doubt, be concise. You can convey a lot more than you realize by carefully choosing your words in a comment. You could also be creative and direct your user/fellow programmer to a text file that fully explains things and isn't included in the script itself. Don't be afraid to be different; don't be afraid to be a non-conformist. Do what's necessary to make your code work well and be understandable to others in the event that you wish to share it.

Post Reply