我编写、维护和使用大量的 bash 脚本。我认为自己是一名 bash 黑客,并努力有一天成为一名 bash 忍者(需要了解更多awk
第一的 )。 bash 需要理解的最重要的功能/挫折之一是引号和随后的参数扩展如何工作。这是有据可查 http://mywiki.wooledge.org/Quotes,并且有充分的理由,在引用参数扩展和分词的神秘世界中存在许多陷阱、错误和新手陷阱。出于这个原因,建议是“对所有内容都进行双引号”,但是如果我希望发生分词怎么办?
In multiple https://github.com/progrium/bashstyle style http://wiki.bash-hackers.org/syntax/expansion/cmdsubst guides https://google.github.io/styleguide/shell.xml#Variable_expansion我找不到在命令替换后安全且正确使用分词的示例。
是什么correct使用不带引号的命令替换的方法?
Example:
我不需要帮助让这个命令正常工作,但这似乎违反了既定模式,如果您想对此命令提供反馈,请将其保留在评论中
docker stats $(docker ps | awk '{print $NF}' | grep -v NAMES)
命令替代返回输出,例如:
container-1 container-3 excitable-newton
这个单行代码使用命令替换来吐出每个正在运行的 docker 容器的名称,并通过分词将它们提供给它们,作为单独的输入docker stats
命令,它接受任意长度的容器名称列表并返回有关它们的一些信息。
如果我使用:
docker stats "$(docker ps | awk '{print $NF}' | grep -v NAMES)"
将有一串换行符分隔的容器名称传递给docker stats
.
这似乎是我想要分词的完美例子,但是外壳检查 http://www.shellcheck.net/不同意,这是否不安全?扩展或替换后是否有使用分词的既定模式?
捕获一个命令的输出并将其传递给另一个命令的安全方法是暂时捕获数组中的输出。这允许在任意分隔符上进行拆分,并防止在捕获输出作为多个字符串传递给另一命令时无意的拆分或通配符。
如果要将空格分隔的字符串读入数组,请使用read -a
:
read -r -a names < <(docker ps | awk '{print $NF}' | grep -v NAMES)
printf 'Found name: %s\n' "${names[@]}"
与不带引号的扩展方法不同,这不会扩展全局。因此,foo[bar]
无法替换为名为的文件系统条目foob
,或者如果不存在这样的文件系统条目并且则使用空字符串nullglob
shell 选项已设置。 (同样地,*
将不再替换为当前目录中的文件列表)。
详细了解行为:read -r -a
读取作为后面选项参数的第一个字符传递的分隔符-d
(如果给定),如果该选项参数为 0 字节,则为 NUL,并根据 IFS 中的字符将结果拆分为字段——默认情况下,IFS 包含换行符、制表符和空格;然后它将这些分割结果分配给一个数组。
此行为不会因 shell 本地配置而发生有意义的变化,但 IFS 除外,它可以在单个命令的范围内进行修改。
mapfile -t
and readarray -t
行为上同样一致,如果可移植性限制不妨碍它们的使用,同样推荐使用。
相比之下,array=( $string )
更依赖于 shell 的配置和设置,and如果 shell 的配置保留默认值,将会表现得很糟糕:
- 使用时
array=( $string )
, if set -f
未设置,通过拆分创建的每个单词$string
被评估为一个全局变量,根据行为的不同而有进一步的差异shopt
设置nullglob
(这会导致一种模式didn't扩展到任何内容以产生空集,而不是默认扩展到 glob 表达式本身),failglob
(这会导致一种模式didn't扩展到任何内容都会导致失败),extglob
, dotglob
和别的。
- 使用时
array=( $string )
,用于分割操作的 IFS 值不能以仅限于该单个操作的方式轻松可靠地更改。相比之下,一个人可以运行IFS=: read
强迫read
仅拆分:
s 不修改该单个值范围之外的 IFS 值;没有等效项array=( $string )
无需存储和重新设置 IFS 即可存在(这是一个容易出错的操作;一些常见的习惯用法[例如赋值给oIFS
或类似的变量名]在常见情况下的操作与意图相反,例如无法在要应用临时修改的块末尾重现未设置或空的 IFS)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)