如何转义 Fish shell 变量以用作 awk 模式?

How to escape Fish shell variable to use as awk pattern?

我正在编写一个函数来列出给定 docker 存储库中我的最新图像:

function docker-latest
      set repo $argv[1]
      docker images | awk "/$repo/ && /latest/{print }"
  end

工作正常…

这是docker images输出

$ docker images
REPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
coaxisopt_daemon                                 latest              86bd3d602074        17 hours ago        830.7 MB
coaxisopt_daemon                                 v1.0.13             86bd3d602074        17 hours ago        830.7 MB
docker.site.fr:5000/coaxis/coaxisopt_daemon     latest              86bd3d602074        17 hours ago        830.7 MB
<none>                                           <none>              da0e5b0fc2a1        17 hours ago        830.7 MB
docker.site.fr:5000/coaxis/coaxisopt_daemon     <none>              9c0175d7d397        18 hours ago        830.7 MB
…

这是我预期的输出:

$ docker-latest coaxis
coaxisopt_daemon                                 latest              86bd3d602074        17 hours ago        830.7 MB
docker.akema.fr:5000/coaxis/coaxisopt_daemon     latest              86bd3d602074        17 hours ago        830.7 MB

直到

但是,当我在字符串末尾放置一些 /(斜杠)字符以过滤推送的图像时:

$ docker-latest coaxis/
awk: cmd. line:1: /coaxis// && /latest/{print }
awk: cmd. line:1:           ^ syntax error

问题

如何转义 repo 变量以便在 awk 模式中安全地使用它?

解决方案

docker images | awk -v repo="$repo"  ' ~ repo &&  == "latest" {print }'

详情: 诀窍是通过 awk 的变量 repo 传递 $repo 并转义 .

肮脏的解决方案

使用sed:

echo "coaxis/" | sed 's!/!\\/!g'

脏,因为它不是真正通用的。

全功能

function docker-latest
      set repo (echo "$argv[1]" | sed 's!/!\\/!g')
      docker images | awk "/$repo/ && /latest/{print }"
  end

如果您必须使用 sed,则将 awk 完全替换为 sed。对于这种情况,它会更清晰和更快(sed 并非总是如此...)

sed 允许在 s 命令后将分隔符更改为任何内容。我选择了#

sed -n "s#\([^ ]*${repo}[^ ]*\) \+latest.*##p"

-n 抑制输出,p 命令仅在匹配时打印。

(如果您对 # 有疑问,您可以选择任何内容,例如 %,或者任何不太可能出现在您的表达式中的内容)