0

I have an array my_array=(foo:123 bar:456 baz:789 lorem:012 ipsum:345)

I want to extract the value after delimiter for a given key

eg. passing foo should return 123. Similarly, passing lorem should return 012

6
  • 3
    Why don't you typeset -A my_array=(foo 123 bar 456 baz 789 lorem 012 ipsum 345) and then use ${my_array[foo]} and ${my_array[lorem]}? Commented Sep 2, 2022 at 11:47
  • @accdias Not working with bash-4. Does it work with bash-5? Commented Sep 2, 2022 at 11:59
  • declare -A my_array=([foo]=123 [bar]=456 [baz]=789 [lorem]=012); echo "${my_array[foo]}" , look for associative array Commented Sep 2, 2022 at 12:04
  • @Fravadona, I don't remember when that syntax for associative arrays were introduced in Bash, but I'm using version 5.1.16(1)-release. Commented Sep 2, 2022 at 12:06
  • 3
    @Fravadona that new type of key-val assignment was added in 5.1 according to git.savannah.gnu.org/cgit/bash.git/tree/NEWS Commented Sep 2, 2022 at 12:24

3 Answers 3

2

If it is acceptable to prepare another (associative) array variable, how about:

#!/bin/bash

my_array=(foo:123 bar:456 baz:789 lorem:012 ipsum:345)
declare -A $(printf "%s\n" "${my_array[@]}" | sed 's/\(.*\):\(.*\)/my_array2[\1]=\2/')

declare -p my_array2

Output:

declare -A my_array2=([bar]="456" [baz]="789" [foo]="123" [lorem]="012" [ipsum]="345" )

Then echo "${my_array2[foo]}" will output 123 as an example.

Please note passing variables or command outputs to declare has a possible vulnerability risk. Make sure the strings in my_array are fully under control.

Sign up to request clarification or add additional context in comments.

6 Comments

Is there a way to generate the associative array dynamically? I have an array of users (foo bar baz). The values should come from output of openssl rand -hex 36
Thank you for the feedback. One question: how do you run the openssl command with the user name? My assumption is something like num=$(openssl <options> "$user"), where "$user" is a user name such as "foo" and the output is "123" which "num" is assigned to. Am I correct?
user will be the key eg. "foo" and the value is a random string from the output of openssl rand -hex 36. Resulting associative array is like - my_array=([foo]="e8db7...d7123" [baz]="4fb67....cfcb"
I solved it :) I think you'll be able to understand better from code. First, we have a users array users=(foo bar baz). Second, create an associative array declare -A users_with_password. Third, for user in ${users[@]}; do users_with_password["$user"]="$(openssl rand -hex 36)"; done
I've totally understood what you want to do and your code is very clear. Thank you and best regards.
|
2

If you just need to access a few keys then you could use a parameter expansion that strips everything but the value of interest from the bash array:

#!/bin/bash
shopt -s extglob

my_array=(foo:123 bar:456 baz:789 lorem:012 ipsum:345)

my_key=lorem
my_val=${my_array[@]/@("$my_key":|!("$my_key":*))/}

echo "$my_val"

note: leading and trailing blanks will be stripped from my_val

012

If you'll be accessing a lot of keys then the previous method is too inefficient so you'll need to build an associative array (bash 4+):

#!/bin/bash

my_array=(foo:123 bar:456 baz:789 lorem:012 ipsum:345)

declare -A my_hash
for elem in "${my_array[@]}"
do
    IFS=':' read -r key val <<< "$elem"
    my_hash["$key"]=$val
done

echo "${my_hash[lorem]}"
012

Comments

0

If you are using older bash versions where associative arrays are not available you could use bash regex matching and parameter substitution:

#!/bin/bash

pattern=${1:-lorem}

arr=(foo:123 bar:456 baz:789 lorem:012 ipsum:345)

for i in "${arr[@]}" ; do
    if [[ "${i}" =~ ^${pattern}:* ]] ; then
        echo "${i##*:}"
    fi
done

Output:

$ ./foo.sh   # default pattern is lorem
012
$ ./script foo
123
$ ./script bar
456
$ ./script baz
789
$ ./script lorem
012
$ ./script ipsum
345

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.