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

时间:2019-09-07 04:01:50

标签: regex shell perl grep gnu-make

我正在尝试:

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

问题是:

  • 我似乎找不到正则表达式来匹配make用来替换我的换行符以解析我的变量的空格。我的正则表达式可以找到正确的起点,但包含.env文件的其余部分,而不是在要提取的值之后停在空白处。

我了解到,当我将文件cat make变成变量时,.env会删除换行符。来自GNU Make docs

  

shell函数执行与反引号('`')相同的功能   在大多数shell中执行:它执行命令扩展。这意味着   将shell命令作为参数,并求值到以下命令的输出   命令。 make对结果所做的唯一处理就是转换   每个换行符(或回车符/换行符对)都放在一个空格中。如果   有一个结尾(回车和换行符)   删除。

但是,我无法获得任何正则表达式来提前识别这些空间来提取变量,或者用另一个字符替换这些空间来辅助提取。

示例:

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

我已经尝试了许多其他正则表达式和命令({{1}},用一个我可以在超前定位的字符替换空格,等等),但是没有运气。

我在做什么错?谢谢。

2 个答案:

答案 0 :(得分:5)

我没有完全了解发生了什么,但是我认为您想从诸如这样的字符串中提取值

#include <string>
#include <fstream>
#include <sstream>

void loadArrays(std::string address[], double amountDue[], const int SIZE)
{
    //Open file for data loading 
    std::ifstream inputFile("Prog3Input.txt");
    std::string line;

    for (int i = 0; i < SIZE; i++)
    {
        std::getline(inputFile, address[i]);
        std::getline(inputFile, line);
        std::istringstream(line) >> amountDue[i];
    }
}

SSH_CREDENTIALS=path/to/my/key ANOTHER_VAR=somethingelse YET_ANOTHER_VAR=yetanothersomething 的路径。

如果这确实是主要目标,那么您将很少错过它:

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

    .*?

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

    grep -o -P '(?<=SSH_CREDENTIALS=).*?(?=[[:space:]])'
    
  • 我看到一个注释掉的grep -o -P '(?<=SSH_CREDENTIALS=)\S+' 代码段,并且Perl被标记了。使用这些工具的正则表达式更简单,无需提前。因此,进入

    sed

    或者再次可以匹配所有连续的非空格字符

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

    我认为您不需要换行符。您也可以使用perl -wne'/SSH_CREDENTIALS=(\S+)/; print $1'

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


经过澄清,似乎整个目标是将变量定义从另一个文件拉入Makefile。如果文件格式与显示的格式完全相同,则可以直接为included,从而提供这些变量定义。一个简单的例子

文件 .env

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

Makefile

[[:space:]]

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

答案 1 :(得分:2)

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

include .env

请参见3.3 Including Other Makefiles