如何在传递 ShellCheck 时通过环境变量将 glob 传递给 shell 脚本

Posted

技术标签:

【中文标题】如何在传递 ShellCheck 时通过环境变量将 glob 传递给 shell 脚本【英文标题】:How to pass a glob to a shell script via an environment variable while passing ShellCheck 【发布时间】:2018-02-06 11:08:48 【问题描述】:

假设我有一个shell 脚本test.sh,它应该回显一些值。我希望能够通过具有全局扩展的环境变量传递这些值:

$ ls
1.js  2.js  test.sh*

$ FOO="*.js" bash ./test.sh
1.js 2.js

简单,你说!随便写

#!/bin/bash
echo $FOO

确实,这行得通。但它没有通过ShellCheck,这要求我们使用隐式通配符/扩展(SC2086)。 (这是公平的;在原始代码中,echo 行是cp $FOO $BAR,实际上我们不想扩展$BAR;这个错误会捕获错误。)

因此,为了使这一点更明确,我希望以下内容可能会起作用:

#!/bin/bash
array=( $FOO )
echo "$array[@]"

但不是:我们最终得到SC2206。

是否有一种规范的方式来做这种事情,这属于 ShellCheck 作者认为的最佳实践? (请随意使用 www.shellcheck.net 上的在线检查器进行测试。)这完全是错误的方法吗? ShellCheck 作者似乎不太可能从未想过这个用例......

【问题讨论】:

在 Twitter 上有人提到 printf %qxargs: twitter.com/stuartpb/status/902411014724976641 。也许有人知道这些会有什么用。 【参考方案1】:

在这种情况下,ShellCheck 的警告似乎没有安全的解决方法。然而,ShellCheck 的诊断并不是普遍的真理。您可能已经注意到,其中一些警告的文档包含一个 Exceptions 部分。对于SC2206,其内容为:

例外情况:

如果您已经小心(通过设置IFSset -f) 按照您的意图进行分词工作,您可以忽略这一点 警告

现在,ShellCheck 提供 directives 以逐个忽略警告:

Shellcheck 指令允许您选择性地忽略警告,并且 在文件中采用 cmets 的形式:

hexToAscii() 
  # shellcheck disable=SC2059
  printf "\x$1"

支持的指令是

disable 禁用警告:

# shellcheck disable=code[,code...]
statement_where_warning_should_be_disabled

...

指令代替 shebang 或紧随其后适用于 整个脚本。否则,它们的范围仅限于以下结构 跟随它(例如 case 语句的所有分支,或整个 函数)。

因此您可以按如下方式抑制警告:

#!/usr/bin/env bash

# The following line is needed so that the shellcheck directive
# below doesn't have global effect
:

# shellcheck disable=SC2206
array=( $FOO )
echo "$array[@]"

【讨论】:

以上是关于如何在传递 ShellCheck 时通过环境变量将 glob 传递给 shell 脚本的主要内容,如果未能解决你的问题,请参考以下文章

Svelte 框架:在运行时将环境变量传递给客户端包

当源文件表示脚本顶部的变量时,为啥 shellcheck 会失败?

如何删除环境变量的“SC2154”警告[关闭]

在运行时将环境变量传递给 Vue 应用程序

如何将环境变量传递给前端 Web 应用程序?

如何将环境变量传递给由 systemd 启动的服务