Makefile 中的多行环境变量
Multiline environment variable in Makefile
我试图从 Makefile 中将一个多行变量传递给一个 cli 程序,但无法这样做。
生成文件
.PHONY: test
test: ## Run the Tests locally
@echo $(SOME_VAR)
r=$(echo $(SOME_VAR) | sed 's/"/\"/g')
python3 test_env_var.py "$(r)"
其中 SOME_VAR
是一个包含多行文本字符串的环境变量(最后,我希望这个变量包含多行 JSON)。您能否建议我如何在 Makefile 中实现此目的?
Python代码:
import sys
print(sys.argv[1])
如果你的 SOME_VAR
确实是一个环境变量——也就是说,在它的环境中从外部提供给 make
—— 那么你可以只依靠你的配方在它自己的环境中继承它:
选项 0
test:
@echo "$${SOME_VAR}"
python3 test_env_var.py "$${SOME_VAR}"
注意 $
字符加倍以避免 make
对其进行解释,以便 shell 执行插值。
但我怀疑你的意思是你在 make
变量中有数据。在这种情况下,您的 echo $(SOME_VAR)
的问题与 python3 test_env_var.py $(SOME_VAR)
的原因几乎相同:不仅是换行符(如果您确实有换行符),还有其他对 [=57= 重要的字符],也会被误解。更重要的是,make
实现通常在单独的 shell 中执行配方的每一行,因此您不能指望在配方的一行中设置 shell 变量并在其中读回其值单独一行。
选项 1
如果您准备假设变量的值不包含任何单引号,那么您可以简单地用它引用:
test:
@echo '$(SOME_VAR)'
python3 test_env_var.py '$(SOME_VAR)'
JSON 数据应该在内部只使用双引号,所以从这个意义上说你应该没问题,但如果数据本身中有任何单引号,那将会中断。
但是请注意,单引号和双引号并不完全类似于 shell。例如,变量扩展、命令替换和反斜杠转义在双引号内被识别,而在单引号内则没有特殊字符被识别。因此,您真的应该考虑使用单引号,完全独立于这些字符在 JSON.
中的不同意义
选项 2
如果你愿意依赖GNUmake
,那么你可以使用它的subst
功能:
test:
@echo '$(subst ','\'',$(SOME_VAR))'
python3 test_env_var.py '$(subst ','\'',$(SOME_VAR))'
将数据中的每个单引号转换为四字符序列 '\''
。由于所有内容都包含在单引号中,这些字符的每次出现都会关闭一个单引号字符串,呈现一个反斜杠转义的单引号(不能出现在单引号字符串内)并开始一个新的单引号字符串。
选项 3
但也不考虑。特别是如果你真的想要多行数据,考虑把它放在一个文件中,然后让配方从那里读取它。如果需要,可以是构建文件。
test:
@echo "$$(cat test-arg)"
python3 test_env_var.py "$$(cat test-arg)"
再次注意 $
字符的加倍。
我试图从 Makefile 中将一个多行变量传递给一个 cli 程序,但无法这样做。
生成文件
.PHONY: test
test: ## Run the Tests locally
@echo $(SOME_VAR)
r=$(echo $(SOME_VAR) | sed 's/"/\"/g')
python3 test_env_var.py "$(r)"
其中 SOME_VAR
是一个包含多行文本字符串的环境变量(最后,我希望这个变量包含多行 JSON)。您能否建议我如何在 Makefile 中实现此目的?
Python代码:
import sys
print(sys.argv[1])
如果你的 SOME_VAR
确实是一个环境变量——也就是说,在它的环境中从外部提供给 make
—— 那么你可以只依靠你的配方在它自己的环境中继承它:
选项 0
test:
@echo "$${SOME_VAR}"
python3 test_env_var.py "$${SOME_VAR}"
注意 $
字符加倍以避免 make
对其进行解释,以便 shell 执行插值。
但我怀疑你的意思是你在 make
变量中有数据。在这种情况下,您的 echo $(SOME_VAR)
的问题与 python3 test_env_var.py $(SOME_VAR)
的原因几乎相同:不仅是换行符(如果您确实有换行符),还有其他对 [=57= 重要的字符],也会被误解。更重要的是,make
实现通常在单独的 shell 中执行配方的每一行,因此您不能指望在配方的一行中设置 shell 变量并在其中读回其值单独一行。
选项 1
如果您准备假设变量的值不包含任何单引号,那么您可以简单地用它引用:
test:
@echo '$(SOME_VAR)'
python3 test_env_var.py '$(SOME_VAR)'
JSON 数据应该在内部只使用双引号,所以从这个意义上说你应该没问题,但如果数据本身中有任何单引号,那将会中断。
但是请注意,单引号和双引号并不完全类似于 shell。例如,变量扩展、命令替换和反斜杠转义在双引号内被识别,而在单引号内则没有特殊字符被识别。因此,您真的应该考虑使用单引号,完全独立于这些字符在 JSON.
中的不同意义选项 2
如果你愿意依赖GNUmake
,那么你可以使用它的subst
功能:
test:
@echo '$(subst ','\'',$(SOME_VAR))'
python3 test_env_var.py '$(subst ','\'',$(SOME_VAR))'
将数据中的每个单引号转换为四字符序列 '\''
。由于所有内容都包含在单引号中,这些字符的每次出现都会关闭一个单引号字符串,呈现一个反斜杠转义的单引号(不能出现在单引号字符串内)并开始一个新的单引号字符串。
选项 3
但也不考虑。特别是如果你真的想要多行数据,考虑把它放在一个文件中,然后让配方从那里读取它。如果需要,可以是构建文件。
test:
@echo "$$(cat test-arg)"
python3 test_env_var.py "$$(cat test-arg)"
再次注意 $
字符的加倍。