首页 > 解决方案 > Makefile 变量 - 替换变量中的空格

问题描述

我在尝试着:

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

问题是:

我知道当cat我将文件放入变量时,会make去除换行符。来自GNU Make 文档

shell 函数执行的功能与大多数 shell 中的反引号 ('`') 执行的功能相同:它执行命令扩展。这意味着它将 shell 命令作为参数并计算命令的输出。make 对结果的唯一处理是将每个换行符(或回车/换行符对)转换为单个空格。如果有尾随(回车和)换行符,它将被简单地删除。

但是,我无法让任何正则表达式提前识别这些空格以提取我的变量,或者用另一个字符替换这些空格以帮助提取。

例子:

.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用我可以在前瞻中定位的字符替换空格等),但没有运气。

我究竟做错了什么?谢谢你。

标签: regexshellperlgrepgnu-make

解决方案


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

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

也就是 的路径SSH_CREDENTIALS

如果这确实是主要目标,那么您几乎没有错过它:

  • 正则表达式中的那.*贪婪的,因为它匹配尽可能多的匹配仍然满足正则表达式。Sicne 后跟一个空格的前瞻,它将匹配字符串中的最后一个空格。相反,你想用 , 来限制它?,所以要使用.*?它匹配以下模式中的第一个(此处为空格)

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

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

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

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

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

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

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

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


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

一个文件.env

SSH_CREDENTIALS=path/to/my/key
ANOTHER_VAR=其他

一个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 一起使用,因此要包含的文件必须满足该格式。


推荐阅读