【问题标题】:How can you access an environment variable that has a space in its name in bash?如何在 bash 中访问名称中包含空格的环境变量?
【发布时间】:2013-08-30 09:00:33
【问题描述】:

运行env 返回“清除工作区=true”。如何在 bash 中访问它?仅供参考,它来自 Jenkins Parameterized Build 参数名称。 ${Clear Workspace} 似乎不起作用。

另外,Jenkins 是如何创建这个环境变量的?在 bash 中运行 Clear Workspace=true 显然不起作用,因为它试图运行带有“Workspace=true”参数的“Clear”命令。

我当然可以将作业参数命名为 Clear_Workspace,但它是以表格形式呈现给用户的,所以我宁愿不这样做。此外,Jenkins 的 Maven 构建插件有几个参数名称,其中包含空格,因此必须可以通过某种方式访问​​它们。

【问题讨论】:

  • 我可以通过env foo\ bar=3 手动设置一个,但还没有找到回应它的方法。
  • @mbratch 你错了。仅仅因为该命令没有给出错误并不意味着您能够设置它。试着说env;你找到了吗?
  • @devnull... 当然,好的。真的没有必要在这里刻薄。但是当我运行命令时,env 会给出一个列表作为输出,它会在变量列表的底部显示foo bar=3。所以它有点像它的工作。它的行为确实有点奇怪。
  • @devnull:我同意 mbratch。通过使用env "foo bar=3" bash。我能够在环境中创建一个带有“foo bar”的 shell。

标签: bash jenkins


【解决方案1】:

您可以使用env 命令模拟这种乐趣

env Clear\ Workspace=true bash

这将为您提供一个设置了环境变量的 shell。

在 bash 4.0 之前应该可以使用的一种 hacky 方法来获取环境变量值:

declare -p Clear\ Workspace | sed -e "s/^declare -x Clear Workspace=\"//;s/\"$//"

从 4.0 开始的 Bash 版本将改为返回错误,并且无法以这种方式提取此类环境变量。

除此之外,您还需要使用本机代码程序或脚本语言将其提取出来,例如

ruby -e "puts ENV['Clear Workspace']"

如果你没有 ruby​​ 的话,这要少得多。

perl -e 'print "$ENV{\"Clear Workspace\"}\n";'

还有

python -c 'import os; print os.environ["Clear Workspace"]'

这是一个原生代码版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv, char **envp) 
{
  char **env;
  char *target;
  int len;
  if (argc != 2) 
  {
    printf("Syntax: %s name\n", argv[0]);
    return 2;
  }
  len = strlen(argv[1]);
  target = calloc(len+2,sizeof(char));
  strncpy(target,argv[1],len+2);
  target[len++] = '=';
  target[len] = '0';
  for (env = envp; *env != 0; env++) 
  {
    char *thisEnv = *env;
    if (strncmp(thisEnv,target,len)==0)
    {
      printf("%s\n",thisEnv+len);
      return 0;
    }
  }
  return 1;
}

【讨论】:

  • 感谢您的详尽回答。我仅限于 bash,因为它是 Jenkins 构建工作的一部分,所以我最终可能会接受你的 hacky 声明 | sed 解决方案。我正在考虑是否值得为了避免用户看到下划线......
  • 路径上通常有一个 ruby​​/perl/python...您可以测试它们,然后如果其中一个丢失,则退回到 hack... 或者您可以使用 HEREDOC创建一个临时源文件,然后使用gcc 或javac 进行编译,然后执行...但我认为使用后备测试ruby/python/perl 来声明hack 会给你一个很好的解决方案
  • 啊,谢谢斯蒂芬。我不知道您可以在 Jenkins 工作中跳入脚本语言。非常便利。如果还没有,我会安装 Python。
  • 这个答案很旧,可能需要更新。最新版本的 bash(5.0+?甚至可能是 4.0+?)可能修复了一个错误,并且使用空格获取环境变量不再起作用:env Clear\ Workspace=true bash -c 'declare -p Clear\ Workspace' 返回bash: line 1: declare: Clear Workspace: not found。
【解决方案2】:

bash 不是唯一可以操纵环境的语言:

$ perl -e '$ENV{"Clear Workspace"}="true"; system "env"' | grep Clear
Clear Workspace=true

如果你在 shell 中,你总是可以解析 env 的输出(未经测试)

value=$(env | while IFS="=" read -r var value; do
                  if [[ $var = "Clear Workspace" ]]; then
                      echo "$value"
                      break
                  fi
              done )

【讨论】:

  • 我只能使用 bash,因为它是 Jenkins 工作的一部分。解析 env 听起来很尴尬,但可能是我唯一可用的解决方案。
  • bash 只是一个调用其他程序的工具。当然,您可以编写一个调用 perl/ruby/python 程序的 bash 脚本。
  • 我可以,假设其中一个安装在服务器上。我必须编写一个脚本并将其放在服务器上的某个位置并引用它,或者将其写入作业的 bash 字段并让解释器解析它,这两种方法都不理想。此外,bash 不仅仅是一个调用其他程序的工具。你可以用它做很多其他的事情。我正在寻找一个简单的 bash 解决方案。
【解决方案3】:

Jenkins 可能正在创建 其他东西,而不是 环境变量。

环境变量中不能有空格。引用http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html:

Shell 中的实用程序使用的环境变量名称和 IEEE Std 1003.1-2001 的实用程序卷仅由大写字母组成 定义的字符中的字母、数字和“_”(下划线) 在便携式字符集中并且不以数字开头。

【讨论】:

  • 我认为@mbratch 已经证明您可以在环境变量名称中包含空格(请参阅问题中的 cmets)。仅仅因为“IEEE Std 1003.1-2001 的 Shell and Utilities 卷中的实用程序使用的环境变量名称仅由大写字母、数字和下划线组成”,这并不意味着 all 环境变量必须仅由这些字符组成。
【解决方案4】:

Java 支持将名称中带有空格的环境变量传递给进程。这是一个证明它的例子:

给定 /tmp/test

#!/bin/sh
env > /tmp/test.out

和Test.java

import java.util.*;
import java.io.*;

public class Test {
    public static void main(String[] args) throws Exception     {
        ProcessBuilder pb = new ProcessBuilder("/tmp/test");
        Map<String, String> env = pb.environment();
        env.put("a b", "true");
        pb.directory(new File("/tmp"));
        Process p = pb.start();
    }
}

运行

> javac Test.java
> java Test
> grep "a b" /tmp/test.out 
a b=true

Jenkins uses the same functionality to start processes.

但是,对于您是否可以从纯 shell 访问它们,而不使用 python、ruby 等,我不确定。我还没有实现它。

您可能希望将它们转换为不带空格的变量,因为它们具有更好的可移植性保证。

【讨论】:

  • 谢谢。我怀疑 Maven 构建插件能够使用它,但我仅限于 bash,因为它只是构建工作的一部分,而不是插件。
【解决方案5】:

以下命令将返回环境变量“Clear Workspace”的值:

set | grep "Clear Workspace" | awk -F'=' '{print $NF}'

您可以分配给另一个没有空格的变量并用于您的目的:

export Clear_Workspace=\`set | grep "Clear Workspace" | awk -F'=' '{print $NF}'\`

试一试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2013-12-15
    • 2012-06-15
    相关资源
    最近更新 更多