linux - 函数内部的错误处理,以便我们可以退出脚本

标签 linux bash shell error-handling

我有两个这样的映射文件,如下所示:

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 1343, 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 脚本。我尝试退出 subshel​​l,但对我没有用。这可能吗?

最佳答案

您可以这样做(结合了我们的专家 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/

相关文章:

linux - 在 RedHat Linux 脚本中使用 cd

bash - Sed 范围并删除最后一个匹配行

linux - 如何制作删除文件的shell脚本

linux - 商品 Linux 存储场的最佳分布式文件系统

php - 关于到期日期的电子邮件 PHP

python - Bash if else 然后与 bash 版本的 sys.exit() 在一行中

regex - 在 bash 中,列出两种类型文件的正则表达式是什么?

linux - 将多个用户批量分配到多个组

linux - 在 bash 中获取参数

linux - 如何以编程方式修改文件日期?