Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider to include readarray and map key value arrays #104

Open
jmorcar opened this issue Apr 24, 2020 · 3 comments
Open

Consider to include readarray and map key value arrays #104

jmorcar opened this issue Apr 24, 2020 · 3 comments

Comments

@jmorcar
Copy link

jmorcar commented Apr 24, 2020

First all, congratulations is a great bash-handbook! I suggest to include examples with readarray, to convert any command linux to array like this:

declare -a array
readarray -t array <<< "$(snmpwalk -v "${VERSION}" -c "${COMMUNITY}" -O n ${DEVICE} ${OID})"

Or include some examples about map arrays. Here an example:

$ declare -A mapkeys
$ mapkeys=( [a]=one [b]=two [c]=three )
$ echo ${mapkeys[a]}

@sumbach
Copy link
Collaborator

sumbach commented Apr 24, 2020

👍 @jmorcar

readarray (aka, mapfile) was added in Bash 4, so I would present this as an alternative to traditional read tricks when Bourne sh or POSIX compatibility isn't a concern. More details and examples in BashFAQ/005.

Associative arrays were added in Bash 4, also. More details and examples, including workarounds for older shells and Bash versions in BashFAQ/006. I'd appreciate if any introduction to associative arrays could mention any complications related to whitespace in and quoting of keys--this tends to trip people up.

@jmorcar
Copy link
Author

jmorcar commented Apr 25, 2020

Okis your give another idea, Indicate historical data about bash 4 with these references or external references to complete the schema for mid/advanced users. Thanks for the reply only I suggested because are functions very useful to create arrays more near to new high level languages.

@terminalforlife
Copy link

I'd appreciate if any introduction to associative arrays could mention any complications related to whitespace in and quoting of keys--this tends to trip people up.

I'm late, but I'd love to weigh in here.

I use associative arrays a lot in BASH. The subscript can be stubborn, but quote-protecting it can sometimes solve the issue. When nothing else works, you could reverse the keys and values or just use regular arrays but with a designated separator between the key and value for each element. The latter often winds up being the best solution, in my experience, because it's more performant and much easier to work with.

An example of the latter solution:

Users=()
while IFS=':' read User _ UserID _; do
    Users+=("$User|$UID")
done < /etc/passwd

for Index in "${Users[@]}"; {
    printf '%s %d\n' ${Index%%|*} "${Index##*|}"
}

It's a contrived example, since it can all easily be done within the while loop without the array, but it does demonstrate what I mean.

To conclude, the best method I have for getting around this limitation of BASH is to just use regular arrays which act like an associative array. In-fact, this sort of approach can lead to some cool results, like something akin to multidimensional arrays.

Here's a great example from one from my programs, CSi3 (cheat sheet for i3WM), of combining a key=value system into an associative array:

https://github.com/terminalforlife/Extra/blob/master/source/csi3/csi3#L140-L235

Although I've just spotted something inefficient: I've repeated the declare builtin many times, which is a pretty bad oversight. I'll have to sort that. Anyway, point being, something very similar can be done with standard arrays to smash a key=value together into the value for the elements. You can also do something similar with a for loop, when an array isn't even needed, like:

for Str in Key1=Value1 Key2=Value2 ...; {
    printf '%s=%s\n' "${Str%%=*}" "${Str#*=}"
}

With this approach, it's important not to greedily match on the value side, else you might remove data from it, whereas you likely won't have the separator as or as part of the key, since that would be silly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants