Makefile 变量 - 替换变量中的空格

Makefile Variable - Replace Whitespace in Variable

我正在尝试:

  1. 导出 .env 文件的路径,以便 make
  2. 可以访问它
  3. 在我的Makefile中,将.env的内容读入一个变量
  4. 将内容解析为我将用于构建和部署我的应用程序的变量

问题是:

我知道当我 cat 我的文件变成一个变量时, make 去除换行符。来自 GNU Make docs:

The shell function performs the same function that backquotes (‘`’) perform in most shells: it does command expansion. This means that it takes as an argument a shell command and evaluates to the output of the command. The only processing make does on the result is to convert each newline (or carriage-return / newline pair) to a single space. If there is a trailing (carriage-return and) newline it will simply be removed.

但是,我无法获得任何正则表达式来识别这些 space 以提取我的变量或用另一个字符替换这些 space 以帮助提取。

示例:

.env:

SSH_CREDENTIALS=path/to/my/key
ANOTHER_VAR=somethingelse
YET_ANOTHER_VAR=yetanothersomething

Makefile:

ENV_FILE_CONTENTS := $(shell cat $(ENV_FILE_PATH) )  # | sed -e 's/[[:space:]]/x/g'
$(info $(ENV_FILE_CONTENTS))

SSH_CREDENTIALS := $(shell echo $(ENV_FILE_CONTENTS) | grep -o -P '(?<=SSH_CREDENTIALS=).*(?=[[:space:]])' )
$(info $(SSH_CREDENTIALS))

SSH_CREDENTIALS := $(shell echo $(ENV_FILE_CONTENTS) | grep -o -P '(?<=SSH_CREDENTIALS=).*(?=\s)' )
$(info $(SSH_CREDENTIALS))

[recipes below]

命令和结果:

$ export ENV_FILE_PATH=./env/.env; make print_env_var
SSH_CREDENTIALS=path/to/my/key ANOTHER_VAR=somethingelse YET_ANOTHER_VAR=yetanothersomething # My .env file without the newlines
path/to/my/key ANOTHER_VAR=somethingelse # Attempt to extract the path to the SSH credentials fails (doesn't recognize whitespace lookahead)
path/to/my/key ANOTHER_VAR=somethingelse # Samething when trying \s instead of [[:space:]]

我尝试了许多其他正则表达式和命令(sed 将 space 替换为我可以在前瞻中定位的字符,等等),但没有成功。

我做错了什么?谢谢。

我不完全明白发生了什么,但我认为您想从字符串中提取值,例如

SSH_CREDENTIALS=path/to/my/key ANOTHER_VAR=somethingelse YET_ANOTHER_VAR=yetanothersomething

SSH_CREDENTIALS的路径。

如果这确实是主要内容 objective,那么您就错过了它:

  • 正则表达式中的 .*greedy 因为它尽可能匹配 所以仍然满足正则表达式。接下来是 whitespace 的前瞻,它将匹配字符串中的 最后一个 whitespace。相反,您想使用 ? 来限制它,因此要使用 .*? 匹配以下模式的 first(此处为 space)

    grep -o -P '(?<=SSH_CREDENTIALS=).*?(?=[[:space:]])'
    

    这在我的测试中工作正常。请注意,您可以简单地匹配非 space 个字符

    grep -o -P '(?<=SSH_CREDENTIALS=)\S+'
    
  • 我看到一个被注释掉的 sed 片段并且 Perl 被标记了。使用这些工具的正则表达式更简单,无需前瞻。所以管道进入

    perl -wne'/SSH_CREDENTIALS=(.*?)\s/; print '
    

    或者,同样,可以匹配所有连续的非space字符

    perl -wne'/SSH_CREDENTIALS=(\S+)/; print '
    

    我假设您不需要换行符。您也可以使用 [[:space:]].

查看您最喜欢的正则表达式资源。在 Perl 中,这将是教程 perlretut and reference perlre.


经过澄清,整个 objective 似乎是将变量定义从另一个文件拉到 Makefile 中。如果文件的格式完全如所示,则可以直接included,从而提供那些变量定义。一个简单的例子

一个文件.env

SSH_CREDENTIALS=path/to/my/key
ANOTHER_VAR=somethingelse

一个Makefile

INCL = /usr/include/boost

include .env

fake: 
    @echo "a variable: $(INCL)"
    @echo "a variable from the included file:   $(SSH_CREDENTIALS)"
    @echo "another variable from included file: $(ANOTHER_VAR)"

使用 make 我们得到预期的打印输出。

请记住,includemakefile 一起使用,因此要包含的文件必须满足该格式。

您的 .env 文件的内容看起来可以直接包含在您的 makefile 中,如下所示:

include .env

3.3 Including Other Makefiles