正确允许 bash 中命令替换的分词

2023-12-25

我编写、维护和使用大量的 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,或者如果不存在这样的文件系统条目并且则使用空字符串nullglobshell 选项已设置。 (同样地,*将不再替换为当前目录中的文件列表)。


详细了解行为: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(使用前将#替换为@)

正确允许 bash 中命令替换的分词 的相关文章

  • Bash - 如何将参数传递给通过标准输入读取的脚本

    我正在尝试从标准输入执行脚本并将参数传递给它 有办法做到吗 假设我有以下内容 cat script sh bash 我如何将参数传递给脚本 我不想这样做 bash script sh arguments 也不是这个 script sh ar
  • 如何从 C 函数创建 shell 命令

    想知道如何获取一组 C 函数并将它们转换为 shell bash 命令 假设我有一组简单的 C 函数 int fn1 some C code for function 1 int fn2 some C code for function 2
  • 如何使用 bash 脚本关闭所有终端,在每个终端中有效地按 Ctrl+Shift+Q

    我经常打开许多终端 其中一些正在运行重要的进程 例如服务器 而另一些则没有运行任何东西并且可以关闭 如果您按 重要 则会弹出确认提示Cntrl Shift Q在其中 如下所示 我想要一个 bash 脚本 它可以关闭所有终端 但将 重要 终端
  • 让 Emacs ansiterm 和 Zsh 更好地发挥作用

    我一直在尝试在 emacs 会话中使用 Zsh 而无需 emacs 重新映射所有 Zsh 键 我发现 ansi term 对此非常有效 但是我仍然遇到一些问题 我输出了很多垃圾字符 我可以用以下方法修复它 Setup proper term
  • 将终端颜色扩展到行尾

    我有一个生成 motd 的 bash 脚本 问题取决于某些终端设置 我不确定颜色是否会延伸到行尾 其他时候则不然 e g v s IIRC 一个只是普通的 gnome 终端 另一个是我的 tmux 术语 所以我的问题是如何才能将其扩展到 8
  • Windows、Emacs、Git Bash 和 shell 命令

    Windows 7 Emacs 24 3 1 git 1 8 1 msysgit 1 我的等效 emacs 文件中有以下内容 if equal system type windows nt progn setq explicit shell
  • 从 bash 脚本运行节点

    很简单 我正在尝试使用 cron 自动运行 nodejs 脚本 但是脚本本身似乎无法运行该文件 我的脚本很简单 usr bin env node node var node assets js update js 但是 在运行此命令时 它返
  • linux下如何获取昨天和前天?

    我想在变量中获取 sysdate 1 和 sysdate 2 并回显它 我正在使用下面的查询 它将今天的日期作为输出 bin bash tm date Y d m echo tm 如何获取昨天和前天的日期 这是另一种方法 对于昨天来说 da
  • 使用 mkfifo 和传输流,这可能吗?

    我想执行一个 bash 脚本来执行以下操作 应用程序 ffmpeg 生成实时传输流 ts 文件 我需要处理这个实时流 执行解复用等 现在我知道这必须通过 FIFO 来完成 但这是我的任务 我需要重定向 ffmpeg 的输出以写入 fifo
  • 如何从 powershell 中设置 bash 的环境变量?

    使用powershell我该如何设置 https askubuntu com q 1205227 45156 the 环境 https stackoverflow com q 5327495 262852变量 这里 特别 https sta
  • 如何从 Linux 的 shell 中删除所有以 ._ 开头的文件?

    确实如标题所示 我已将许多文件从 Mac 复制到 Raspberry Pi 这导致了许多以前缀开头的多余文件 我想删除以以下开头的文件夹中的每个文件 我该怎么做 尝试类似的方法 cd path to directory rm rf 或者 如
  • 在 shell 脚本中查找和替换

    是否可以使用 shell 在文件中搜索然后替换值 当我安装服务时 我希望能够在配置文件中搜索变量 然后在该值中替换 插入我自己的设置 当然 您可以使用 sed 或 awk 来完成此操作 sed 示例 sed i s Andrew James
  • execlp 多个“程序”

    我想运行类似的东西 cat file tar base64 myprogram c base64 d tar zvt I use execlp运行该进程 当我尝试运行类似的东西时cat它有效 但如果我尝试运行base64 d tar zvt
  • Bash - 在 perl 正则表达式中使用变量以及匹配组

    这是我在 stackoverflow 上的第一篇文章 如果我错过了一些重要的内容 请原谅我 我目前遇到以下问题 目标是根据我准备的文件列表动态替换端口号find 这些文件中的所有端口均以数字 4 开头 有 5 位数字 现在是棘手的部分 我只
  • Bash 脚本:#!/bin/bash 是什么意思? [复制]

    这个问题在这里已经有答案了 在 bash 脚本中 什么是 bin bash第一行是什么意思 UPDATE 有区别吗 bin bash and bin sh 这就是所谓的shebang http en wikipedia org wiki S
  • 如何显示 NUL 分隔数据的中间管道结果?

    如何组合以下两个命令 find print0 grep z pattern tr 0 n find print0 grep z pattern xargs 0 my command 进入单个管道 如果我不需要 NUL 分隔符那么我可以这样做
  • Mac OS X 中 Bash 脚本中的 SFTP 命令

    我需要使用 SFTP 和 SSH 从 Mac 主机将文本文件传输到远程 PC freeSSH 这两个连接在本地网络中 那么有没有办法从 Bash 脚本内部运行 SFTP 命令 使用提供的用户名和密码 我已经尝试过一些脚本expect 但我没
  • 如何使用AWK脚本检查表的所有列数据类型? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 在这里 我正在检查表中第一列的数据类型 但我想知道AWK中表的所有列数据类型 我尝试过 但只能获得一列数据类型 例如 Column 1
  • 为什么减法返回 - 符号

    我对简单的减法有疑问 但我不明白出了什么问题 我的代码 start date s N cut b1 13 Treatment end date s N cut b1 13 delta expr end start echo delta de
  • 如何在 Xcode 4.2 中创建 Shell 脚本目标?

    我想知道是否有人知道 XCode 4 1 如何创建 shell 脚本 该选项不存在 但在最新版本中可能会被称为其他名称 塔 在导航器中选择您的项目 单击 添加目标 为空目标选择 聚合 添加构建阶段 gt 添加运行脚本 单击构建阶段并编辑运行

随机推荐