LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   sed used as parsing tool problem in bash (https://www.linuxquestions.org/questions/programming-9/sed-used-as-parsing-tool-problem-in-bash-712568/)

freeindy 03-18-2009 01:53 PM

sed used as parsing tool problem in bash
 
Hi.

I have a config file looking like this

my.config
Code:

Section "One"
  VAR_A = Apple
  VAR_B = Steel
EndSection

Section "Two"
  VAR_A = Orange
  VAR_B = Wood
EndSection

Section "Three"
  #VAR_A = Banana
  VAR_B = Plastic
EndSection

I want to be able to parse the variable out from defined section using a tool, called get_param.sh.
Please note, if a variable is commented (#). it should be ignored

get_params.sh
Code:

#!/bin/bash
# Enough parameters passed?
if [ $# -lt 3 ]; then
    echo
    echo "Usage: get_param.sh <file> <section> <parameter>"
    echo
    exit 1
fi

#Does file exist?
if [ ! -e $1 ] ; then
    echo
    echo -n "Error: File "
    echo -ne '\E[0;36m'"\033[2m$1\033[0m "
    echo not found!
    echo
    exit 1
fi

#Get all the parameter from the section
RESULT=`sed -n "/$2/,/EndSection/p" $1`

#Ignore commented ones and retreive the parameter
RESULT=`echo $RESULT | sed '/^ *#/d;s/#.*//' $1 | grep -w $3`

#remove all beginning white spaces
RESULT=`echo $RESULT | awk -F= '{print $NF}' | awk '{sub("^ ", "", $0); print $0
}'`

#return value
eval echo $RESULT

exit 0

I thought my script was working but there is some bug somewhere I can't find.

when I call
Code:

./get_param.sh my.config One VAR_A
I get
Code:

Orange
where as I should get Apple.

Can anyone see why?

Thanks a million.
Indy

Hko 03-18-2009 02:39 PM

Quote:

Originally Posted by freeindy (Post 3479702)
Code:

#Get all the parameter from the section
RESULT=`sed -n "/$2/,/EndSection/p" $1`


The output of this sed command consists of multiple lines. Newlines are lost when assigning multiple lines to a variable (at least this way).

Because of that, the "grep" command does not work as you seem to expect:
Quote:

Originally Posted by freeindy (Post 3479702)
Code:

#Ignore commented ones and retreive the parameter
RESULT=`echo $RESULT | sed '/^ *#/d;s/#.*//' $1 | grep -w $3`


Also, here you echo text into sed and specify a file for sed to read at the same time. I think this command will read the entire file again and what is echo-ed through the pipe (|) will be ignored. So the effect of the first command is lost.

BTW after: /^ *#/d, this: s/#.*// is not needed as all lines starting with '#' with or without leading spaces will already be deleted by the first part (/^ *#/d). This shouldn't effect functioning of the script though, just as a side note.

I think it is easier done in one single sed command:
Code:

RESULT=`sed -n -e "/Section[ \t]*\"$2\"/,/EndSection/s/[ \t]*[^#]\($3\)[ \t]*=[ \t]*\([^ \t]*\)[ \t]*/\1=\2/p" $1`
eval "$RESULT"
echo "VAR_A: $VAR_A"
echo "VAR_B: $VAR_B"
exit 0


jschiwal 03-18-2009 03:30 PM

For extracting parts of certain records, you can have embedded regions.

Code:

sed '/Section "One"/,/EndSection/ {
                                    /[^#]* VAR A/s/.*= //
}
' file

You could use ...'"$VAR"'... to use variable parameters.

One thing to think of it you want to use your config script to set variables is to remove the spaces around the `=' and `eval' the result.

freeindy 03-19-2009 03:07 AM

Thanks lads,

Hko, I just replace your code and it works. However, there is one small thing. I know the spaces between cause problems but there are so many config files that I don't want to go and change all of them.

The problem that still remains is...

when a variable is set like this:
Code:

VAR_A = Apple Orange Banana
the result is
Code:

VAR_A=AppleOrange Banana.
Could this be fixed? I would like the result to be:
Code:

VAR_A=Apple Orange Banana.
jschiwal, I couldn't get your to work. It just printed out the whole file

Indy

jschiwal 03-19-2009 10:51 PM

I was in a hurry and didn't test it. I did want to point out that you can have subregions.

It should use the -n option. I also misread the data and used "VAR A" in my example and not "VAR_A":
Code:

$ sed -n '/Section "Three"/,/EndSection/{
                                      /^[^#]*VAR_A/s/.* = //p }' testfile

schiwalj@FAR_DESKTOP21 ~
$ sed -n '/Section "Three"/,/EndSection/{
                                      /^[^#]*VAR_B/s/.* = //p }' testfile
Plastic

The "^[^#]" part is changed slightly from my first example. It ignores lines that have the octothorpe character before the variable.

Here is the second thing I mentioned:
Code:

$ sed -n '/Section "Three"/,/EndSection/{
                                          /VAR/s/[[:space:]]*=[[:space:]]*/=/p }' testfile
  #VAR_A=Banana
  VAR_B=Plastic

It removes whitespace around the equals sign. So you could eval the results to set the variables. "eval $(...)"

This is a method I used in an ogg2mp3 script. I used ogginfo and a sed filter to produce a number of "tag=value" lines which I eval'ed to set these variables. Then I used the variables in lame to set the tags of the mp3 file that had been in the ogg file I downloaded.


All times are GMT -5. The time now is 10:49 PM.