简体   繁体   English

Bash:检查关联数组中是否存在键

[英]Bash: Check if key exists in associative array

Goal:目标:

All I want to do is to check if a USER_PARAMETERS_KEYs[j] exists in RPM_PARAMETERS_HASH associative array.我要做的就是检查RPM_PARAMETERS_HASH关联数组中是否存在USER_PARAMETERS_KEYs[j] I have one array and one associative arrays as the following:我有一个数组和一个关联 arrays 如下:

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.我的问题是当${USER_PARAMETERS_KEYS[j]}变得等于dstIPField时,因为它在关联数组中有一个空字符串值,所以尽管密钥在那里,但不满足 if 条件。

使用 bash 你可以只使用-v选项[[

[[ -v RPM_PARAMETERS_HASH[${USER_PARAMETERS_KEYS[j]}] ]]

It looks like you can make it work by splitting up the steps (first evaluate the key, then use the -v test):看起来您可以通过拆分步骤来使其工作(首先评估密钥,然后使用-v测试):

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

In the linuxhint article: "Associative Arrays Bash Examples" 1 Under Example #5 it shows:在 linuxhint 文章:"Associative Arrays Bash Examples" 1在示例 #5 下,它显示:

$ 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.请注意,“searchKEY”可以是文字值,也可以是扩展为文字值的变量。 Kudos to the author of the article that uncovered this "+_" operator on shell variables as a way to test for the key existence.感谢这篇文章的作者,他在 shell 变量上发现了这个“+_”运算符,作为测试密钥存在的一种方式。 I was unable to tease this out of the GNU BASH Reference Manual 2 .我无法从 GNU BASH 参考手册2 中梳理出这一点。 I am sure it is related to parameter expansion but I never realized that it would show associative (hash) array member existence.我确定它与参数扩展有关,但我从未意识到它会显示关联(散列)数组成员的存在。

@sailnfool - kudos to You for finding this solution. @sailnfool - 感谢您找到此解决方案。 The "-v" solution doesn't work for me. “-v”解决方案对我不起作用。

Regarding "+_" - in fact the "operator" is the "+" sign, as states in a "Shell Parameter Expansion" in the Bash Reference Manual :关于“+_”-实际上,“运算符”是“+”号,正如Bash 参考手册中的“Shell Parameter Expansion”中所述

" ${parameter:+word} If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted." " ${parameter:+word}如果参数为空或未设置,则不替换任何内容,否则替换单词的扩展。"

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

Posting an answer here to add a bit of clarification to answers from @acan and @sailnfool.在此处发布答案以对@acan 和@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).我发现我需要通过一些示例场景来完全掌握它们所描述的方法的细微差别(感谢@sailnfool 为您在答案中创建的示例脚本)。 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.无论如何,如果我只是简单地回复@sailnfool 的帖子并附上评论,我在这里的评论就不会很清晰,所以这里是 FBO。

Clarifying the logic/outcomes of @sailnfool's script/answer:澄清@sailnfool 的脚本/答案的逻辑/结果:

  1. If an array is defined, but a specific element (key) within the array has never been defined: both queries return a result of, "array element does not exist"如果定义了一个数组,但从未定义过数组中的特定元素(键):两个查询都返回“数组元素不存在”的结果
  2. If an array element's value previously existed and has been unset: both queries return "array element does not exist"如果数组元素的值以前存在且未设置:两个查询都返回“数组元素不存在”
  3. If an array element's (key's) value is not NULL: both queries return "array element exists"如果数组元素的(键)值不是 NULL:两个查询都返回“数组元素存在”
  4. If an array element's value is NULL: 1st query returns "array element does exist"如果数组元素的值为 NULL:第一个查询返回“数组元素确实存在”
  5. If an array element's value is NULL: 2nd query returns "array element does not exist"如果数组元素的值为 NULL:第二次查询返回“数组元素不存在”

I couldn't quite tell from the original question whether the poster was attempting to derive whether or not a particular array element existed (ie 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:如果目的是确定是否曾经设置过特定的数组元素(包括将其设置为 NULL),则使用此方法:

[[ ${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.所以,重新加盖......它们之间的唯一区别是第一种方法(上面显示的示例)在数组元素存在但设置为 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.而第二种分支方法只会在数组元素被定义时返回一个真正的路径(数组元素存在),并且包含一个非空值。

Bottom Line底线

Your need scenario 1 : tell when an array element is defined and = any value, including NULL您需要的场景 1 :告诉何时定义数组元素和 = 任何值,包括 NULL

Use: 1st branch method [[ ${arr[c]+1} ]] && echo "array key exists" ||使用:第一个分支方法 [[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist" echo "数组键不存在"

Your need scenario 2 : tell me when an array element is defined and contains a non-NULL value您需要的场景 2 :告诉我何时定义数组元素并包含非 NULL 值

Use: either logic branching method [[ ${arr[c]+1} ]] && echo "array key exists" ||使用:任一逻辑分支方法 [[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist" or [[ ${arr[c]:+1} ]] && echo "array key exists" || echo "数组键不存在" 或 [[ ${arr[c]:+1} ]] && echo "数组键存在" || echo "array key does not exist" echo "数组键不存在"

Your need scenario 3 : tell me when an array element is not defined at all (ie never defined or was defined and subsequently unset )您需要的场景 3 :告诉我何时根本没有定义数组元素(即从未定义或已定义,随后未设置

Use: either logic branching method [[ ${arr[c]+1} ]] && echo "array key exists" ||使用:任一逻辑分支方法 [[ ${arr[c]+1} ]] && echo "array key exists" || echo "array key does not exist" or [[ ${arr[c]:+1} ]] && echo "array key exists" || echo "数组键不存在" 或 [[ ${arr[c]:+1} ]] && echo "数组键存在" || echo "array key does not exist" echo "数组键不存在"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM