LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Help with sed script in bash (https://www.linuxquestions.org/questions/programming-9/help-with-sed-script-in-bash-865095/)

corp769 02-25-2011 11:18 PM

Help with sed script in bash
 
Code:

#!/bin/bash
VARR=`cat /proc/asound/cards | grep HDMI | cut -c 1-2`
VARX="defaults.ctl.card $VARR"
VARY="defaults.pcm.card $VARR"
FILE1="alsa"
FILE2="alsa.new"
echo $VARX
echo $VARY
sed "s/defaults\.ctl\.card*/'$VARX'/g" $FILE1 > $FILE2

Ok, this is what I have right now. Normally, if I need help with anything, I learn it on my own. Well, I thought I knew sed, and apparently I don't... I tried writing this for someone else, and this has given me trouble, so since the user pretty much figured it out on his own, here it goes.

Say VARR=1, so VARX and VARY contain the above text, appended by 1. What I am trying to do is replace the text "defaults.ctl.card 0" by VARX and "defaults.pcm.card 0" by VARY. The contents of FILE1 is the file being used to search for both text fields, and FILE2 is the output file. I tried using single quotes, double quotes, and a mixture of both, and no go whatsoever. So my question... What is the proper way of searching for text within a file and replacing with a variable?

syg00 02-26-2011 12:38 AM

You don't (shouldn't) need the single quotes at all in that case.
I suspect you need to look more carefully at the regex on the LHS of the substitution.

David the H. 02-26-2011 12:52 AM

Without seeing the actual input and output, I can only guess at the real problem. But I think using * alone won't match what you want. You need to use .* instead. Otherwise, as long as you use double-quotes, you shouldn't have any problem with the variable expansion.

How about something like this:
Code:

#!/bin/bash
FILE1="alsa"
FILE2="alsa.new"
VARR=$( grep "HDMI" /proc/asound/cards | cut -c 2 )
sed -r "s/(defaults\.(ctl|pcm)\.card [01])/\1 $VARR/g" $FILE1 > $FILE2

Notes:

$(..) is recommended over `..`

grep can take the filename as an argument, so you don't need cat.

cut -c 1-2 will also give you the blank space in front of the number, and I think you only want the number itself, so I used -c 2 instead.

You can bypass the intermediate variables and just use the original value in your sed expressions.

Finally, with a little regex back-referencing and some grouping, gnu sed will allow you to do the whole thing in a single expression. Or you could also do something like this, which should be more portable:
Code:

sed -e "s/defaults\.ctl\.card [01]/defaults.ctl.card $VARR/g" \
-e "s/defaults\.pcm\.card [01]/defaults.pcm.card $VARR/g"  $FILE1 > $FILE2


corp769 02-26-2011 06:19 AM

Quote:

Originally Posted by David the H. (Post 4271665)
Without seeing the actual input and output, I can only guess at the real problem. But I think using * alone won't match what you want. You need to use .* instead. Otherwise, as long as you use double-quotes, you shouldn't have any problem with the variable expansion.

How about something like this:
Code:

#!/bin/bash
FILE1="alsa"
FILE2="alsa.new"
VARR=$( grep "HDMI" /proc/asound/cards | cut -c 2 )
sed -r "s/(defaults\.(ctl|pcm)\.card [01])/\1 $VARR/g" $FILE1 > $FILE2

Notes:

$(..) is recommended over `..`

grep can take the filename as an argument, so you don't need cat.

cut -c 1-2 will also give you the blank space in front of the number, and I think you only want the number itself, so I used -c 2 instead.

You can bypass the intermediate variables and just use the original value in your sed expressions.

Finally, with a little regex back-referencing and some grouping, gnu sed will allow you to do the whole thing in a single expression. Or you could also do something like this, which should be more portable:
Code:

sed -e "s/defaults\.ctl\.card [01]/defaults.ctl.card $VARR/g" \
-e "s/defaults\.pcm\.card [01]/defaults.pcm.card $VARR/g"  $FILE1 > $FILE2


Wow, thanks for the clear description. One thing though.... you mentioned the following - "cut -c 1-2 will also give you the blank space in front of the number, and I think you only want the number itself, so I used -c 2 instead." On my machine, even though your example worked flawlessly, my cut command worked too. But I'm not complaining, and thank you for the example. I learned a lot from that.

Thanks again man!

Josh

David the H. 02-26-2011 03:25 PM

Well, I was basing it on the output I got from my own /proc/asound/cards, which shows a space at the beginning of each card line. I suppose it's possible you get something different. More likely it's actually there in yours too, but isn't affecting anything, as the size of the blank space doesn't usually matter in most configuration-type files.

But since you only want to extract a single digit, it's hard to see how having it cut two characters would be desirable no matter what the actual effect.

corp769 02-26-2011 03:27 PM

I know what I did - I copied the cut command out of one of my other scripts and pasted it in (Yes, I was that lazy - I was drinking....) and when I did paste it in, it worked. I guess bash took the space out. Or maybe gremlins inside my computer saw the space and killed it? Oh well, works as advertised :)


All times are GMT -5. The time now is 07:41 AM.