我在bash
喜欢
myArray=('red' 'orange' 'green')
我想做一些像
这样的事情echo ${myArray['green']}
在这种情况下会输出2
。这可以实现吗?
答案 0 :(得分:67)
这样做:
#!/bin/bash
my_array=(red orange green)
value='green'
for i in "${!my_array[@]}"; do
if [[ "${my_array[$i]}" = "${value}" ]]; then
echo "${i}";
fi
done
显然,如果你把它变成一个函数(例如get_index()) - 你可以把它变成泛型
答案 1 :(得分:25)
您必须在使用
之前声明您的阵列declare -A myArray
myArray=([red]=1 [orange]=2 [green]=3)
echo ${myArray['orange']}
答案 2 :(得分:12)
没有。您只能使用bash
中的整数索引一个简单数组。关联数组(在bash
4中引入)可以用字符串索引。但是,它们没有提供您要求的反向查找类型,没有特殊构造的关联数组。
$ declare -A myArray
$ myArray=([red]=0 [orange]=1 [green]=2)
$ echo ${myArray[green]}
2
答案 3 :(得分:9)
答案 4 :(得分:2)
我喜欢这个解决方案:
let "n=(`echo ${myArray[@]} | tr -s " " "\n" | grep -n "green" | cut -d":" -f 1`)-1"
变量n将包含结果!
答案 5 :(得分:2)
这只是chepner显示的另一种初始化关联数组的方法。
不要忘记您需要明确declare
或使用-A
属性设置关联数组。
i=0; declare -A myArray=( [red]=$((i++)) [orange]=$((i++)) [green]=$((i++)) )
echo ${myArray[green]}
2
这消除了对硬编码值的需要,并且不太可能最终导致重复。
如果要添加许多值,可能有助于将它们放在不同的行上。
i=0; declare -A myArray;
myArray+=( [red]=$((i++)) )
myArray+=( [orange]=$((i++)) )
myArray+=( [green]=$((i++)) )
echo ${myArray[green]}
2
假设你想要一个数字和小写字母数组(例如:用于菜单选择),你也可以这样做。
declare -a mKeys_1=( {{0..9},{a..z}} );
i=0; declare -A mKeys_1_Lookup; eval mKeys_1_Lookup[{{0..9},{a..z}}]="$((i++))";
如果你再运行
echo "${mKeys_1[15]}"
f
echo "${mKeys_1_Lookup[f]}"
15
答案 6 :(得分:1)
这可能适用于数组,
my_array=(red orange green)
echo "$(printf "%s\n" "${my_array[@]}")" | grep -n '^orange$' | sed 's/:orange//'
输出:
2
如果要在tsv文件中找到标题索引,
head -n 1 tsv_filename | sed 's/\t/\n/g' | grep -n '^header_name$' | sed 's/:header_name//g'
答案 7 :(得分:1)
另一种棘手的单线:
index=$((-1 + 10#0$(IFS=$'\n' echo "${my_array[*]}" | grep --line-number --fixed-strings -- "$value" | cut -f1 -d:)))
功能:
-1
小室:
value
为非空按执行顺序分解说明:
IFS=$'\n' echo "${my_array[*]}"
将数组扩展分隔符(IFS
)设置为新行char并扩展数组
grep --line-number --fixed-strings -- "$value"
匹配的grep:
--line-number
或-n
)--fixed-strings
或-F
;禁用正则表达式)允许以-
(--
)开头的元素
cut -f1 -d:
仅提取行号(格式为<line_num>:<matched line>
)
$((-1 + 10#0$(...)))
减去1,因为行号是1索引的,数组是0索引的
如果$(...)
不匹配:
0
(10#0
)$(...)
符合:
10#0
为前缀;即10#02
,10#09
,10#014
等10#
前缀强制以10为底的十进制数字,而不是八进制使用awk
代替grep
,cut
和bash算法:
IFS=$'\n'; awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}" <<< "${my_array[*]}"
功能:
小室:
按执行顺序分解说明:
IFS=$'\n' [...] <<< "${my_array[*]}"
将数组扩展分隔符(IFS
)设置为新行char并扩展数组
awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}"
匹配整行并打印索引为0的行号
${value//\"/\\\"}
用转义版本替换$value
中的双引号答案 8 :(得分:0)
在zsh中你可以做到
xs=( foo bar qux )
echo ${xs[(ie)bar]}
参见zshparam(1)小节下标标志
答案 9 :(得分:0)
更简洁一点,适用于Bash 3.x:
my_array=(red orange green)
value='green'
for i in "${!my_array[@]}"; do
[[ "${my_array[$i]}" = "${value}" ]] && break
done
echo $i
答案 10 :(得分:0)
这将输出查询的基于0的数组索引(此处为“橙色”)。
echo $(( $(printf "%s\n" "${myArray[@]}" | sed -n '/^orange$/{=;q}') - 1 ))
如果查询未在数组中发生,则以上输出-1
。
如果查询在数组中多次出现,则上面的命令将输出查询第一次出现的索引。
由于此解决方案调用sed,因此我怀疑它是否可以与该线程中的某些纯bash解决方案竞争以提高效率。
答案 11 :(得分:0)
这显示了一些用于返回数组成员索引的方法。 该数组将不适用的值用于第一个和最后一个索引, 提供从1开始的索引并提供限制。
while循环是一种有趣的迭代方法,它具有截止值, 为了生成数组值的索引, 循环的主体仅包含用于空操作的冒号。 重要的部分是i直到匹配为止的迭代, 或超过可能的匹配。
函数indexof()会将文本值转换为索引。
如果值不匹配,该函数将返回错误代码,该错误代码可能是
在测试中用于执行错误处理。
与数组不匹配的输入值将超过范围限制(-gt, -lt)
测试。
有一个测试(主代码)可以循环使用好/坏值,前三行已注释掉,但是请尝试一些变体以查看有趣的结果(lines 1,3 or 2,3 or 4
)。我包括了一些考虑错误情况的代码,因为它很有用。
最后一行代码将调用具有已知正确值“绿色”的indexof函数,该函数将回显索引值。
indexof(){
local s i;
# 0 1 2 3 4
s=( @@@ red green blue @o@ )
while [ ${s[i++]} != $1 ] && [ $i -lt ${#s[@]} ]; do :; done
[ $i -gt 1 ] && [ $i -lt ${#s[@]} ] || return
let i--
echo $i
};# end function indexof
# --- main code ---
echo -e \\033c
echo 'Testing good and bad variables:'
for x in @@@ red pot green blue frog bob @o@;
do
#v=$(indexof $x) || break
#v=$(indexof $x) || continue
#echo $v
v=$(indexof $x) && echo -e "$x:\t ok" || echo -e "$x:\t unmatched"
done
echo -e '\nShow the index of array member green:'
indexof green
答案 12 :(得分:0)
myArray=('red' 'orange' 'green')
echo ${myArray[@]}
arrayElementToBeRemoved='orange'
echo "removing element: $arrayElementToBeRemoved"
# Find index of the array element (to be kept or preserved)
let "index=(`echo ${myArray[@]} | tr -s " " "\n" | grep -n "$arrayElementToBeRemoved" | cut -d":" -f 1`)-1"
unset "myArray[$index]"
echo ${myArray[@]}
答案 13 :(得分:0)
我自己也想要类似的东西并避免循环,想出了......
DROP TEMPORARY TABLE IF EXISTS tmp_users_normalized;
CREATE TEMPORARY TABLE tmp_users_normalized
SELECT userkey, username, 1 AS PropertyType, customproperty1 AS Value
FROM users u
UNION ALL
SELECT userkey, username, 2 AS PropertyType, customproperty2 AS Value
FROM users u
UNION ALL
SELECT userkey, username, 3 AS PropertyType, customproperty3 AS Value
FROM users u
;
SELECT *
FROM tmp_users_normalized tun
JOIN ents e ON tun.Value LIKE '%etc%'
;
... 如果找不到元素,则标准输出不会受到污染...
myArray=('red' 'orange' 'green')
declare -p myArray | sed -n "s,.*\[\([^]]*\)\]=\"green\".*,\1,p"
之后我用谷歌搜索,发现了这个问题,并认为我会分享;)
答案 14 :(得分:-1)
简单的解决方案:
my_array=(red orange green)
echo ${my_array[*]} | tr ' ' '\n' | awk '/green/ {print NR-1}'