我有两个这样的映射文件,如下所示:
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
都有主映射和辅助映射。例如: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脚本。我尝试退出子shell,它对我没用。这可能吗?
答案 0 :(得分:2)
你可以这样做(包含我们的大师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
在函数中进行错误检查是一种更好的做法。
如果您不希望该函数退出,可以在调用该函数后检查调用者代码中的数组大小。
如果您使用的是不支持namerefs的Bash版本,则可以对数组使用全局变量,假设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。
相关: