【问题标题】:Make variable substitution in string在字符串中进行变量替换
【发布时间】:2020-04-28 15:52:40
【问题描述】:

假设我定义了一个json文件:

foo.json

{"key":"${VALUE}"}

制作文件:

export VALUE=bar
SHELL=/usr/bin/env bash
foo=$(shell cat foo.json)

bar:
    @echo "$(foo)"

问题是:我如何通过 make 的变量替换或 echo 的 BASH 替换来扩展 ${VALUE} 变量,以便在 OUTPUT 上保留有效 JSON 文件中的双引号(是 make保留它们,是的,echo $(foo) 还评估变量——但删除双引号——是的,我不关心换行符被删除)?

至于这一切的原因,假设我有一个例程,它需要一个相当于一种语言(而不是配置)的富有表现力的 JSON 文件,并且我正在使用 Make 来控制系统:

.PHONY: generator

# in the language of control theory
generator: $(foreach q,${Qm},.Qmarked-startup-$q)
    application $@ -i <(pseudo code: {envsubst $@.json})

.Qmarked-startup-%: $(pseudo code: q0 dependencies ... )
    # $* here is a verb
    application $* -i <(pseudo code: {envsubst $*.json})

【问题讨论】:

  • 您究竟希望该 makefile 打印什么?
  • 如果您向我们展示您真正想做的事情会更好。这(使用$(shell ...))不太可能完成您真正想做的事情,因为它总是会丢弃所有换行符(例如)。如果我们知道您真正想要实现的目标,而不是 echo ...,那么可能有更好的方法来实现。
  • @MadScientist 已编辑和更新。
  • 如果您的示例中没有注释// foo.json,那么您不关心换行会更清楚...如果您有,那么您的整个 JSON 文件将被注释删除换行符时退出...
  • @MadScientist 该评论是为了表明降价的上下文在文件 foo.json 中。

标签: makefile gnu-make


【解决方案1】:

如果你想从 Make 的环境中扩展变量,你可以使用eval 来扩展赋值中的变量。

假设您不介意按照@MadScientists 的评论将所有行合并在一起,您可以找出 cmets 并将 json 组合成一行,如下所示:

export VALUE:=bar

foo:=$(shell grep -v "^\S*//" foo.json)
$(info foo=[$(foo)])

$(eval foo2:=$(shell grep -v "^\S*//" foo.json))
$(info foo2=[$(foo2)])

bar:
        @echo "from recipe: foo2=[$(subst ",\",$(foo2))]"

$(subst ",\",...) 在发送到 bash 之前转义引号。这输出:

foo=[{"key":"${VALUE}"}]
foo2=[{"key":"bar"}]
from recipe: foo2=[{"key":"bar"}]

注意:安全考虑——如果外部人员可以访问 foo.json,那么他们可以使用制造商的权限让 make 运行任何他们想要的。

【讨论】:

  • 我认为你不需要配方中的$(subst ...)。只需将 echo 放在单引号中,这样 shell 就不会弄乱内容:@echo 'from recipe: foo2=[$(foo2)]'
  • 另外我认为您可以忽略 cmets:OP 在他们的环境中可能实际上没有任何内容。我认为它很简单:$(eval foo = $(shell cat foo.json))(或者如果您愿意,可以使用 := 简单扩展 foo
【解决方案2】:

如果你运行这个 Makefile :

export VALUE=bar
SHELL=/usr/bin/env bash
foo=$(shell cat foo.json)

bar:
    $(warning $(foo))

您可以看到 $(foo) 确实包含双引号。但是 $VALUE 没有展开。

你可以试试这个:

export VALUE=bar
SHELL=/usr/bin/env bash
foo=$(shell VALUE=$(VALUE) envsubst < foo.json)

bar:
    @echo '${foo}'

【讨论】:

    猜你喜欢
    • 2015-04-02
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 2020-02-04
    • 1970-01-01
    • 2011-09-29
    相关资源
    最近更新 更多