我在 bash
中有类似以下代码
myArray=('red' 'orange' 'green')
我想做类似的事情
echo ${myArray['green']}
在这种情况下,输出将为
2
。这可行吗?这将完成它:
#!/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
for i in "${!my_array[@]}"; do
。此外,如果您只想查找第一个索引,则可以在找到索引后使用break
来终止循环。 - gniourf_gniourf${!my_array[@]}
中,!
表示反转或否定操作符。它用于返回数组my_array
中所有键的列表。 - bodacydo!
是什么意思,后来尝试了一下,发现它不是列出数组中的所有值,而是从零开始列出索引。 - Fredrick Gauss!
表示返回元素的索引而不是元素的值。 - DocSalvager在使用前必须声明数组
declare -A myArray
myArray=([red]=1 [orange]=2 [green]=3)
echo ${myArray['orange']}
$ declare -A myArray
$ myArray=([red]=0 [orange]=1 [green]=2)
$ echo ${myArray[green]}
2
更加简洁,适用于Bash 3.x:
my_array=(red orange green)
value='green'
for i in "${!my_array[@]}"; do
[[ "${my_array[$i]}" = "${value}" ]] && break
done
echo $i
&& break
替换为echo $i && break
。 - undefined另一个棘手的一行代码:
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
) 设置为换行符并扩展数组。
grep --line-number --fixed-strings -- "$value"
查找匹配项:
--line-number
或 -n
)--fixed-strings
或 -F
;禁用正则表达式)允许以 -
开头的元素(--
)
cut -f1 -d:
仅提取行号(格式为 <line_num>:<matched line>
)
$((-1 + 10#0$(...)))
由于行号是从1开始计数的,而数组是从0开始计数的,因此需要减去1。
如果$(...)
没有匹配:
0
(10#0
),并且不返回任何内容$(...)
匹配:10#0
;例如:10#02
,10#09
,10#014
等10#
将强制使用十进制数字而非八进制数字使用awk
而不是grep
、cut
和bash算术:
IFS=$'\n'; awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}" <<< "${my_array[*]}"
特点:
注意事项:
按执行顺序分解的说明:
IFS=$'\n' [...] <<< "${my_array[*]}"
将数组扩展分隔符 (IFS
) 设置为换行符并扩展数组。
awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}"
匹配整行并打印0索引行号
${value//\"/\\\"}
将$value
中的双引号替换为转义版本printf "%s\n" "${arr[@]}" | [...]
比IFS=$'\n' [...] <<< "${arr[*]}"
更具可移植性和鼓励性。此外,值得注意的是awk解决方案将打印每个匹配索引。要仅返回第一个/最左边的索引,可以在打印后的块中调用awk函数exit
(即awk "... {print NR-1; exit}"
)。要返回最后一个/最右边的索引,请将NR-1存储在变量中并在END处打印:awk "... {result = NR-1} END {print result}"
。 - Joshua Skrzypekmy_array=(red orange green)
echo "$(printf "%s\n" "${my_array[@]}")" | grep -n '^orange$' | sed 's/:orange//'
输出:
2
如果你想要在一个tsv文件中找到header的索引位置,
head -n 1 tsv_filename | sed 's/\t/\n/g' | grep -n '^header_name$' | sed 's/:header_name//g'
这只是初始化关联数组的另一种方法,就像chepner展示的那样。
不要忘记你需要显式地使用-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
如果你需要反复查找数组中的值,可以通过关联数组构建一个反向索引。
my_array=(red orange green)
declare -A my_ass_arr
for i in ${!my_array[@]}; do my_ass_arr[${my_array[$i]}]=$i; done
this_val="green"
echo ${my_ass_arr[$this_val]}
这样你只需要遍历数组一次。我不确定bash在关联数组的索引和搜索方面的底层操作,但这可能比每次进行蛮力搜索更快。
xs=( foo bar qux )
echo ${xs[(ie)bar]}