Arrays bash字符串数组
我有一个复杂的脚本,它必须根据运行的位置使用不同的代码位 动态地确定这一点没有什么好办法,相反,它必须硬编码并在执行时查找 我想我需要的是这样的东西Arrays bash字符串数组,arrays,bash,hash,Arrays,Bash,Hash,我有一个复杂的脚本,它必须根据运行的位置使用不同的代码位 动态地确定这一点没有什么好办法,相反,它必须硬编码并在执行时查找 我想我需要的是这样的东西 { "location": { "type1": [ "hostname1", "hostname2", "hostname 3" ], "type2": [ "hostname4, "hostname5", "hostname6"], "type3": [ "hostname7, "hostname8", "hostname9
{
"location": {
"type1": [ "hostname1", "hostname2", "hostname 3" ],
"type2": [ "hostname4, "hostname5", "hostname6"],
"type3": [ "hostname7, "hostname8", "hostname9"]
}
}
case $array[$(hostname)] in #pseudocode
type1) bash $dir/type1.sh;;
type2) bash $dir/type2.sh;;
*) bash $dir/type3.sh;;
esac
然后,我可以通过某种方式查询以找到其值包含脚本执行器主机名值的键
在ruby中,这就像创建散列并查找值一样简单。
这在bash中可能吗
hash.key(Socket.gethostname)
无论如何,它将被硬编码到脚本中,简单地考虑使用<代码> CASE < /代码>:
case $(hostname) in
(hostname1|hostname2|hostname3) bash "$dir/type1.sh";;
(hostname4|hostname5|hostname6) bash "$dir/type2.sh";;
(*) bash "$dir/type3.sh";;
esac
可以在bash中存储字符串数组,也可以在bash中存储映射,但不能将数组作为值存储在映射中 但是,如果您的类型名仅使用shell变量名中有效的字符,则可以通过将每个数组存储在单独的变量中,并使用间接引用查找或迭代变量名来进行欺骗
#!/bin/bash
[[ $BASH_VERSION ]] && ! [[ $BASH_VERSION =~ ^([0123][.]|4[.][012]) ]] || {
echo "This requires bash 4.3 or later" >&2
exit 1
}
# we're declaring any variable name starting with loc_ to be part of our data
loc_type1=( "hostname1" "hostname2" "hostname3" )
loc_type2=( "hostname4" "hostname5" "hostname6" )
loc_type3=( etc etc etc )
# map from type to hostnames; "hosts_for_type type1" will emit hostnames 1-3
hosts_for_type() {
local -n type_arr="loc_$1"
printf '%s\n' "${type_arr[@]}"
}
# do the heavy lifting to build a map from hostnames to types
# this only needs to be run once for the given data
declare -g -A type_for_host=( )
build_hosttype_map() {
local varname typename host
# abort if inverse map is already built so this only runs once
(( ${#type_for_host[@]} )) && return
for varname in "${!loc_@}"; do
declare -n locarr="$varname"
typename=${varname#loc_}
for host in "${locarr[@]}"; do
type_for_host[$host]=$typename
done
done
}
# map from hostname to type; uses inverse map built above.
type_for_host() {
build_hosttype_map
printf '%s\n' "${type_for_host[$1]}"
}
根据上述定义:
$ type_for_host hostname1
type1
$ hosts_for_type type1
hostname1
hostname2
hostname3
(如果您想处理包含所有可能字符的数据元素,您需要将
'%s\n'
格式字符串更改为'%s\0'
,从换行分隔符切换为NUL;但是,由于我们的输入域目前仅由有效主机名组成,因此不会立即调用)。Waitaminute。您是按主机还是按类型进行查找?您的伪代码表示前者,但您的字典是为后者创建的。您知道这更聪明、更简单。感谢您指出。如果您修复了引号,您将有一个很好的解决方案,正如另一个答案下面的注释所指出的。修复了引号和间距/缩进;感谢大卫和查尔斯指出这一点!哦,天哪,这比我想象中的巴什还要难看。我真的很感激你在这方面所做的努力。语法上的丑陋和概念上的丑陋之间有很大的区别——这里有很多语法,但它是定义良好的语法,无论运行时环境、数据等如何,都将以一致的方式运行(当然,除了用loc
前缀划出我们保留的变量名称空间)。这与$(find…)中文件的之类的东西相比,这些东西看起来并不可怕,但实际上它们在运行时所做的事情充满了极端情况和丑陋。即使是公认的答案,尽管简短,也有一些地方有另一个更微妙的地方(我认为更严肃)有点难看:$dir/type1.sh
如果目录名中有空格,或者IFS
值包含该名称中的字符(例如/
),则会以意外的方式运行;它必须是“$dir”/type1.sh
(或“$dir/type1.sh”
)才是正确的,没有先决条件或警告。有些人只是喜欢漫画部分而不是莎士比亚。。。虽然引用了更正,但它非常简短,而且切中要害……毫无疑问——另一个(更正后)应该是可接受的答案;它比这更适合OP的即时用例。(如果有人需要动态构建地图,然后高效地进行任意数量的反向查找,那么这个答案很有价值,因此我认为它为这个问题增加了一些价值,但现在它不是OP的最佳选择)。