11

I am new to shell script. I have a file app.conf as :

[MySql]
user = root
password = root123
domain = localhost
database = db_name
port = 3306

[Logs]
level = logging.DEBUG

[Server]
port = 8080

I want to parse this file in shell script and want to extract mysql credentials from the same. How can I achieve that?

2
  • Which shell are you using? bash, ksh, /bin/sh, ...? Commented Mar 27, 2014 at 11:11
  • Hi @glennjackman, it is /bin/sh. Commented Mar 27, 2014 at 11:12

4 Answers 4

13

I'd do this:

pw=$(awk '/^password/{print $3}' app.conf)

user=$(awk '/^user/{print $3}' app.conf)


echo $pw
root123

echo $user
root

The $() sets the variable pw to the output of the command inside. The command inside looks through your app.conf file for a line starting password and then prints the 3rd field in that line.

EDITED

If you are going to parse a bunch of values out of your config file, I would make a variable for the config file name:

CONFIG=app.conf
pw=$(awk '/^password/{print $3}' "${CONFIG}")
user=$(awk '/^user/{print $3}' "${CONFIG}")

Here's how to do the two different ports... by setting a flag to 1 when you come to the right section and exiting when you find the port.

mport=$(awk '/^\[MySQL\]/{f=1} f==1&&/^port/{print $3;exit}' "${CONFIG}")
sport=$(awk '/^\[Server\]/{f=1} f==1&&/^port/{print $3;exit}' "${CONFIG}")
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks a lot, but I am getting an error : user: not found. My shell script file is : #!/bin/sh user = $(awk '/^user/{print $3}' /root/app/config/app.conf)
Remove the spaces around the equals sign.
Are you on Windows? If so, try changing the single quotes into doube quotes. If that fails, try checking your file has no weird characters with "cat -vet yourfile". If that fails, edit your answer and post the exact code you are having trouble with and I'll take a look.
Thanks a lot Mark. It is working. It was my stupid mistake in understanding what you were saying (apparently I was removing spaces from app.conf, as I never thought that spaces in assignment statements in shell script would matter). Now what I understood is spaces are not allowed in shell script for var=value and $n gives me the nth part separated by space in a line matched by a regex provided to awk. Also $0 would give me the entire line where the match was found.
I added some hints to the end of my answer... for your next question ;-)
|
6

You will want to search for "shell ini file parser". I would start with something like this:

ini_get () {
    awk -v section="$2" -v variable="$3" '
        $0 == "[" section "]" { in_section = 1; next }
        in_section && $1 == variable {
            $1=""
            $2=""
            sub(/^[[:space:]]+/, "")
            print
            exit 
        }
        in_section && $1 == "" {
            # we are at a blank line without finding the var in the section
            print "not found" > "/dev/stderr"
            exit 1
        }
    ' "$1"
}

mysql_user=$( ini_get app.conf MySql user )

Comments

5

Using awk:

awk -F ' *= *' '$1=="user"||$1=="password"{print $2}' my.cnf
root
gogslab

1 Comment

Yes sure. This awk uses field separator as = with optional spaces on either side. Once field are separated it prints 2nd field when 1st field is either user OR password
2

I ran in a similar problem yesterday and thought the best solution might be, if you get an associative array like "key - value" after parsing the file.

I you like to see a running example have a look at https://github.com/philippkemmeter/set-resolution/blob/master/set-resolution.

Adapted to your problem, this might work:

function receive_assoc_declare_statement {
    awk -F '=' 'BEGIN {ORS=" "}
    { 
        gsub(/[ \t]+/, "", $1); 
        gsub(/[ \t]+/, "", $2);
        print "[" $1 "]=" $2
    }' app.conf
}

eval 'declare -A CONF=('`receive_assoc_declare_statement`')'

You then have access to for instance user via ${CONF[user]}.

The gsub is trimming keys and values, so that you can use tab etc. to format your config file.

It's lacking sections, but you could add this functionality using sed to create one config array per section:

sed -n '/\[MySql\]/, /\[/ {p}' test.removeme | sed '1 d; $ d'

So answering your question in total, this script might work:

MYSQL=`sed -n '/\[MySql\]/, /\[/ {p}' app.conf | sed '1 d; $ d' | awk -F '=' 'BEGIN {ORS=" "}
{
    gsub(/[ \t]+/, "", $1); 
    gsub(/[ \t]+/, "", $2);
    print "[" $1 "]=" $2
}' `
eval 'declare -A MYSQL=('$MYSQL')'

The other sections correspondingly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.