Reputation: 81
Goal:
All I want to do is to check if a USER_PARAMETERS_KEYs[j]
exists in RPM_PARAMETERS_HASH
associative array. I have one array and one associative arrays as the following:
Predefined:
declare -a USER_PARAMETERS_KEYS='([0]="userField" [1]="fUserField" [2]="srcIPField" [3]="srcPortField" [4]="dstIPField" [5]="dstPortField" [6]="dateField" [7]="timeField")'
declare -A RPM_PARAMETERS_HASH='([timeField]="Time" [userField]="User-Name" [dstIPField]="" [srcIPField]="Source-IP-Address" [dstPortField]="Target-UDP-Port" [fUserField]="Full-Name" [dateField]="Date" [srcPortField]="Source-UDP-Port" )'
I implemented the following:
if [[ ${RPM_PARAMETERS_HASH[${USER_PARAMETERS_KEYS[j]}]} ]] ; then
Problem
My problem is when ${USER_PARAMETERS_KEYS[j]}
becomes equal to dstIPField
since it has an empty string value in the associative array, so the if condition is not satisfied although the key is there.
Upvotes: 5
Views: 6669
Reputation: 1144
Posting an answer here to add a bit of clarification to answers from @acan and @sailnfool. I found that I needed to run through some example scenarios to full grasp the nuances of the method they both describe (thanks to @sailnfool for the example script you created in your answer). At any rate, my comments here would not have been very legible if I simply replied to @sailnfool's post with a comment, so here goes FBO.
Clarifying the logic/outcomes of @sailnfool's script/answer:
I couldn't quite tell from the original question whether the poster was attempting to derive whether or not a particular array element existed (i.e. whether the specific array element had been declared or not) versus whether or not a particular array element had a value (not null).
If the intent is to determine whether or not a specific array element has ever been set (including setting it equal to NULL), then use this method:
[[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist"
For example:
declare -A arr
arr["c"]=""
[[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist"
or
declare -A arr
arr["c"]=''
[[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist"
If a user's intent is to detect when an array element existed and was subsequently unset, or when a specific array element has never been created, either of the two branching methods are going to return the same result. Namely, that the element does not exist. So, re-capping... the only difference between them is the ability of the first method (examples shown above) to branch when an array element exists but is set equal to NULL. While the 2nd branching method will only return a true path (array element exists) when the array element has been defined, and contains a non-null value.
Your need scenario 1: tell when an array element is defined and = any value, including NULL
Use: 1st branch method [[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist"
Your need scenario 2: tell me when an array element is defined and contains a non-NULL value
Use: either logic branching method [[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist" or [[ ${arr[c]:+1} ]] && echo "array key exists" || echo "array key does not exist"
Your need scenario 3: tell me when an array element is not defined at all (i.e. never defined or was defined and subsequently unset)
Use: either logic branching method [[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist" or [[ ${arr[c]:+1} ]] && echo "array key exists" || echo "array key does not exist"
Upvotes: 1
Reputation: 141145
With bash you can just use -v
option to [[
:
[[ -v RPM_PARAMETERS_HASH["${USER_PARAMETERS_KEYS[j]}"] ]]
Upvotes: 3
Reputation: 11
@sailnfool - kudos to You for finding this solution. The "-v" solution doesn't work for me.
Regarding "+_" - in fact the "operator" is the "+" sign, as states in a "Shell Parameter Expansion" in the Bash Reference Manual:
"${parameter:+word}
If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted."
And in the introduction: "Omitting the colon results in a test only for a parameter that is unset."
$ declare -A arr; arr["a"]="x"
$ echo ${arr[a]+_}
_
$ echo ${arr[a]+1}
1
$ echo "|${arr[c]+1}|"
||
$ arr["c"]=''
$ [[ ${arr[c]+1} ]] && echo "ok" || echo "nok"
ok
$ [[ ${arr[c]:+1} ]] && echo "ok" || echo "nok"
nok
Upvotes: 1
Reputation: 61
In the linuxhint article: "Associative Arrays Bash Examples"1 Under Example #5 it shows:
$ if [ ${ArrayName[searchKEY]+_} ]; then echo "Exists"; else echo "Not available"; fi
Note that the "searchKEY" could either be a literal value or a variable that expands to a literal value. Kudos to the author of the article that uncovered this "+_" operator on shell variables as a way to test for the key existence. I was unable to tease this out of the GNU BASH Reference Manual2. I am sure it is related to parameter expansion but I never realized that it would show associative (hash) array member existence.
Upvotes: 0
Reputation: 74645
It looks like you can make it work by splitting up the steps (first evaluate the key, then use the -v
test):
declare -a USER_PARAMETERS_KEYS='([0]="userField" [1]="fUserField" [2]="srcIPField" [3]="srcPortField" [4]="dstIPField" [5]="dstPortField" [6]="dateField" [7]="timeField")'
declare -A RPM_PARAMETERS_HASH='([timeField]="Time" [userField]="User-Name" [dstIPField]="" [srcIPField]="Source-IP-Address" [dstPortField]="Target-UDP-Port" [fUserField]="Full-Name" [dateField]="Date" [srcPortField]="Source-UDP-Port" )'
j=4
key=${USER_PARAMETERS_KEYS[j]}
[[ -v RPM_PARAMETERS_HASH[$key] ]] && echo yes # output: yes
Upvotes: -1