AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 693613
Accepted
Ortomala Lokni
Ortomala Lokni
Asked: 2022-03-09 13:23:19 +0800 CST2022-03-09 13:23:19 +0800 CST 2022-03-09 13:23:19 +0800 CST

如何使用环境变量在 zsh 中存储标志?

  • 772

我正在使用kubectl和 zsh,我想将命名空间标志存储在环境变量中。

而不是写:

kubectl get pods -n mynamespace

我想做类似的事情:

n='-n mynamespace'
kubectl get pods $n

但这样做,我得到:

No resources found in  mynamespace namespace.

in注意单词和之间的两个空格mynamespace。

如果我运行kubectl get pods -n mynamespace,我会获得正确的输出:

NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          16m

这里会发生什么?为什么输出中的单词in和之间有两个空格mynamespace?以及如何将命名空间标志存储在环境变量中?

environment-variables zsh
  • 2 2 个回答
  • 425 Views

2 个回答

  • Voted
  1. Best Answer
    Arkadiusz Drabczyk
    2022-03-09T13:52:42+08:002022-03-09T13:52:42+08:00

    zsh 不对变量执行分词,而是将其值作为单个参数传递。我这里没有 kubectl,但你可以用任何东西重现该行为,例如 mkdir:

    var='-p a/b/c/d'
    comp% mkdir $var
    mkdir: invalid option -- ' '
    Try 'mkdir --help' for more information.
    

    您可以使用以下方法调用相同的错误:

    comp% mkdir '-p a/b/'
    mkdir: invalid option -- ' '
    Try 'mkdir --help' for more information.
    

    您可以使用以下命令查看 zsh 真正在做什么strace -f mkdir $var:

    execve("/usr/bin/mkdir", ["mkdir", "-p a/b/c/d"], 0x7ffce5e6afb0 /* 61 vars */) = 0
    

    正如this answer on SO中所建议的, 您需要启用分词,例如:

    comp% mkdir -p ${=var}
    

    在您的情况下,它将是:

    kubectl get pods ${=n}
    
    • 2
  2. Stéphane Chazelas
    2022-03-10T08:39:35+08:002022-03-10T08:39:35+08:00

    不要将 shell 变量(或任何语言的变量)与环境变量混淆。环境变量是var=value语法中的字符串数组,在执行时与参数数组一起传递给命令。与命令行参数一样,它们用于将字符串从一个命令传递到另一个不相关的命令。

    Shell 具有这样的特殊性,它们将一些标量变量映射到它们在启动时收到的一些环境变量(名称是有效的 shell 变量名并且不会与特殊的 shell 变量冲突的环境变量),而其他语言使用 API,例如至于getenv()检索它们(或将它们映射到特殊的关联数组,如 perl 的ENVIRONofawk或%ENVof ),但这并不意味着 shell 不能拥有自己的变量,也不限于标量变量。

    如果要在变量中存储多个值,则可以使用数组/列表变量。zsh 从 1991 年的 2.0 版本开始支持数组(早于 bash),实际上是 shell 引入了array=(foo bar)声明它们的语法(类似于set array=(foo bar)70 年代后期的 csh),现在 ksh93、bash、mksh 和 yash 也支持。

    在zsh中,你会这样做:

    options=(-n mynamespace)
    kubectl get pods $options
    

    在 中yash,你会这样做:

    options=(-n mynamespace)
    kubectl get pods "$options"
    

    而在 ksh93/bash 中(zsh 也支持,它还具有不丢弃空元素的优点,并且yash):

    options=(-n mynamespace)
    kubectl get pods "${options[@]}"
    

    现在,数组不能导出为环境变量,它们只是非 NUL 字节的纯字符串。

    如果您必须将这两个参数kubectl作为一个环境变量传递,则需要以某种方式使用某种形式的编码将它们组合起来,以从字符串数组中获取一个字符串,然后将其拆分以将这两个参数取回 for kubectl。

    您选择将它们与空格连接起来作为粗略的编码。请注意,这意味着每个元素都不能包含空格。

    要使用任意分隔符连接单词, in zsh,您可以使用j参数扩展标志,并拆分s参数扩展标志:

    words=(-n mynamespace) # two arguments in an array variable
    export ENV_VAR=${(j[ ])mynamespace} # joined into an environment variable
    

    然后从zsh在该环境中调用的另一个ENV_VAR环境变量已映射到$ENV_VARshell 变量:

    words=(${(s[ ])ENV_VAR}) # split back into an array on space
    

    在没有参数扩展标志的 bash 或 ksh93 中,您可以使用第一个字符(恰好是其默认值中的空格字符)"${array[*]}"连接数组元素,并使用 split+glob 进行拆分:$IFS

    words=(-n mynamespace) # two arguments in an array variable
    IFS=' '
    export ENV_VAR="${words[*]}" # joined into an environment variable
    

    在另一个bash/ksh93在那个环境中:

    IFS=' '
    set -o noglob
    words=($ENV_VAR) # leaving a variable unquoted is split+glob in bash/ksh93!
                     # here with glob disabled above.
    

    您也可以在 中执行此操作zsh,但仅限在 sh 或 ksh 仿真模式下。默认情况下,zsh 不会在不带引号的参数扩展时执行 split+glob,您必须明确请求每个:$=var用于拆分,$~var用于通配。因此,如果由于某种原因您想使用 IFS 拆分而不是j/s参数扩展标志,您可以这样做:

    IFS=' '
    words=($=ENV_VAR) # explicitly request IFS-splitting, here on space only.
                      # no need to disable globbing globally like in ksh93/bash/yash
                      # as globbing is not done implicitly by default upon
                      # parameter expansion in zsh.
    

    现在,我不知道kubectl,但是对于以标准方式解析选项的应用程序(例如使用标准getopt()C 函数),对于带有参数的选项,例如 with grep -e expression,您可以传递两个-eandexpression参数或一个-eexpression参数,所以在这里,您仍然可以将-n其及其mynamespace参数存储在标量变量中:

    option=-nmynamespace
    kubectl get pods $option
    

    (请注意,如果$option是空的,它的扩展,因为它没有被引用不会导致任何参数被传递给kubectl。虽然这(以及空数组元素被丢弃的事实)可能被认为是一个错误,但在这里它会碰巧是你想要什么)。

    • 1

相关问题

  • 符号链接所有点文件和目录

  • $PAGER 可以包含空格吗?

  • 我可以在环境中手动设置多个代理吗?

  • 如何在`zsh`中增加一个动态命名的变量

  • 为什么我不能在 zsh 中定义一个名为 path 的只读变量?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve