17

I have a file that I need to look up a value by key using a shell script. The file looks like:

HereIsAKey This is the value

How can I do something like:

MyVar=Get HereIsAKey

and then MyVar should equal "This is the value". The key has no whitespace and the value should be everything following whitespace after the key.

6 Answers 6

24

if HereIsAKey is unique in your file, try this with grep:

myVar=$(grep -Po "(?<=^HereIsAKey ).*" file)
Sign up to request clarification or add additional context in comments.

5 Comments

Great! One question as I'm new to scripting. I want a function like: GetConfigValue and it would take HereIsAKey as a parameter. How can I put the passed parameter into the regular expression?
This is fine: echo "(grep -Po \"(?<=^" "$1" " ).*\" file)", but I'm having trouble assigning it to a variable. I get MyParam: command not found.
Hi @Kent, I used your solution but I am getting two = instead of one = sign. My file is slightly different than OP. I have file with: [email protected] MyVar2=ab/xyz12. There is already a single = in file. Can you please let me know what needs to be changed here?
@Preeti it's hard to give a working solution without seeing your origin file. but, FYI, the = is not a problem for look ahead. you can give this a try myVar=$(grep -Po "(?<=^MyKey=).*" file) I suggest you understand what the regex means, then you're able to solve many problems in the same kind in the future.
9

If you only need one variable at a time, you can do something like this:

#!/bin/bash
cat file | while read key value; do
  echo $key
  echo $value
done

The problem with this solution: The variables are only valid inside the loop. So don't try to do $key=$value and use it after the loop.

Update: Another way is I/O redirection:

exec 3<file
while read -u3 key value; do
  eval "$key='$value'"
done
exec 3<&-
echo "$keyInFile1"
echo "$anotherKey"

6 Comments

The left-hand side of an assignment cannot be a parameter expansion
found a solution for the assignment
That's a really unnecessarily verbose fix. Just take your existing while read loop, put <file on the end instead of cat file on the beginning, and you're done. See also BashFAQ #24.
@CharlesDuffy Today, I wonder myself about it. I copied it from somewhere and believed it was the smartest possible implementation. Debians installers contain lots of such redirections...
They typically do that because they want to be able to use the original standard input inside the loop. Of course, it's possible that some of them just did a cargo cult copy from a script where this was actually necessary.
|
9

If you don't have a grep that supports Perl-compatible regular expressions, the following seems to work:

VAR=$(grep "^$KEY " file | cut -d' ' -f2-)

1 Comment

Not only is this more readable and portable, it can also handle variable whitespace size if you cut on the equals: grep "^$KEY" $FILE | cut -d'=' -f2-
5

If the file is unsorted, lookups will be slow:

my_var=$( awk '/^HereIsAKey/ { $1=""; print $0; exit}' value-file )

If the file is sorted, you can get a faster lookup with

my_var=$( look HereIsAkey value-file | cut -d ' ' -f 2- )

1 Comment

"The look utility appeared in Version 7 AT&T Unix."
0

I use a property file that is shared across multiple languages, I use a pair of functions:

load_properties() {
    local aline= var= value=
    for file in config.properties; do
        [ -f $file ] || continue
        while read aline; do
            aline=${aline//\#*/}
            [[ -z $aline ]] && continue
            read var value <<<$aline
            [[ -z $var ]] && continue
            eval __property_$var=\"$value\"
            # You can remove the next line if you don't need them exported to subshells
            export __property_$var
        done <$file
    done
}

get_prop() {
    local var=$1 key=$2
    eval $var=\"\$__property_$key\"
}

load_properties reads from the config.properties file populating a set of variables __property_... for each line in the file, get_prop then allows the setting of a variable based on loaded properties. It works for most of the cases that are needed.

Yes, I do realize there's an eval in there, which makes it unsafe for user input, but it works for what I needed it to do.

Comments

0
get () {
    while read -r key value; do
        if [ "$key" = "$1" ]; then
            echo "$value"
            return 0
        fi
    done
    return 1
}

The two return statements aren't strictly necessary, but provide nice exit codes to indicate success or failure at finding the given key. They can also help distinguish between "the key has a empty string for the value" and "the key was not found".

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.