我有两个这样的映射文件,如下所示:
primary_mapping.txt
{1=[343, 0, 686, 1372, 882, 196], 2=[687, 1, 1373, 883, 197, 736, 1030, 1569], 3=[1374, 2, 884, 737, 198, 1570], 4=[1375, 1032, 1424, 3, 885, 1228], 5=[1033, 1425, 4, 200, 886]}
secondary_mapping.txt
{1=[1152, 816, 1488, 336, 1008], 2=[1153, 0, 817, 337, 1489, 1009, 1297], 3=[1, 1154, 1490, 338], 4=[1155, 2, 339, 1491, 819, 1299, 1635], 5=[820, 1492, 340, 3, 1156]}
在上面的映射文件中,每个clientId
都有primary和secondary的映射。例如:clientId 1
有 343, 0, 686, 1372, 882, 196
主映射和 1152, 816, 1488, 336, 1008
二次映射。对于其他 clientIds
也是如此。
下面是我的 shell 脚本,它在其中打印特定 clientid 的主要和次要映射:
#!/bin/bash
mapfiles=(primary-mappings.txt secondary-mappings.txt)
declare -a arr
mappingsByClientID () {
id=$1 # 1 to 5
file=${mapfiles[$2]} # 0 to 1
arr=($(sed -r "s/.*\b${id}=\[([^]\]+).*/\1/; s/,/ /g" $file))
echo "${arr[@]}"
}
# assign output of function to an array
# this prints mappings for clientid 3. In general I will take this parameter from command line.
pri=($(mappingsByClientID 3 0))
snd=($(mappingsByClientID 3 1))
现在假设如果我们找不到特定 clientid
的主要或次要映射,那么我想通过记录消息以非零状态代码退出 shell 脚本。我尝试退出 subshell,但对我没有用。这可能吗?
最佳答案
您可以这样做(结合了我们的专家 Charles Duffy 的所有重要建议):
mappingsByClientID () {
(($# != 3)) && { echo "Insufficient arguments" >&2; exit 1; }
declare -n arr=$1 # for indirect assignment (need **Bash 4.3 or above**)
id=$2 # 1 to 5
file=${mapfiles[$3]} # 0 to 1
[[ $file ]] || { echo "No mapping file found for id '$id', type '$2'" >&2; exit 1; }
[[ -f $file ]] || { echo "File '$file' does not exist" >&2; exit 1; }
# Note: the word boundary `\b` is not supported in ERE
# See post: https://stackoverflow.com/q/27476347/6862601
if ! grep -q "[{ ]$id=" "$file"; then
echo "Couldn't find mapping for id '$id' in file '$file'" >&2
exit 1
fi
mapfile -t arr < <(sed -r "s/.*[{ ]$id=\[([^]\]+).*/\1/" "$file" | tr -s '[ ,]' '\n')
if ((${#arr[@]} == 0)); then
echo "Couldn't find mapping for id '$id' in file '$file'" >&2
exit 1
fi
echo "${arr[@]}"
}
现在在没有子 shell $()
的情况下调用函数,以便函数内部的 exit
实际上退出脚本:
mappingsByClientID pri 3 0
mappingsByClientID sec 3 1
最好在函数中进行错误检查。
如果您不希望函数退出,可以在调用函数后在调用方代码中检查数组大小。
如果你使用的 Bash 版本不支持 namerefs,你可以对数组使用全局变量,假设 arr
是全局的,那么:
arr=() # initialize the global
mappingsByClientID 3 0
pri=("${arr[@]}") # make a copy of the global array into pri
mappingsByClientID 3 1
sec=("${arr[@]}") # make a copy of the global array into sec
相应地修改 mappingsByClientID
以使用全局变量而不是 nameref。
相关:
关于linux - 函数内部的错误处理,以便我们可以退出脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49952090/