Bash gmake$(shell)函数中的转义

Bash gmake$(shell)函数中的转义,bash,makefile,environment-variables,gnu-make,Bash,Makefile,Environment Variables,Gnu Make,我有一个环境变量GITHUB_REFS,我想对它执行一些bashism操作,并从GNU makefile的另一个变量GITHUB_分支中捕获结果。我天真的做法是这样的: SHELL:=/bin/bash GITHUB_BRANCH:=$(shell echo "${GITHUB_REF#refs/heads/}") HASH := \# foo := $(shell echo "${GITHUB_REF$(HASH)refs/heads/}") 如果我单独运行Bashim,它可以正常工作,

我有一个环境变量GITHUB_REFS,我想对它执行一些bashism操作,并从GNU makefile的另一个变量GITHUB_分支中捕获结果。我天真的做法是这样的:

SHELL:=/bin/bash
GITHUB_BRANCH:=$(shell echo "${GITHUB_REF#refs/heads/}")
HASH := \#

foo := $(shell echo "${GITHUB_REF$(HASH)refs/heads/}")
如果我单独运行Bashim,它可以正常工作,但是当运行上面的makefile时,它会失败:

Makefile:2: *** unterminated call to function 'shell': missing ')'.  Stop.
我试图逃离as\,因为它是一个貌似有理的罪魁祸首,事实上,然后Makefile可以工作,而bashism不能。双重转义会再次出现相同的错误

那么我如何才能实现这一点呢?

可以使用\来转义,但您也忘记了转义$

此Makefile可以工作:

SHELL:=/bin/bash

foo := $(shell echo "$${SHELL\#/bin/}")

all:
    echo $(foo)

您还需要将美元符号加倍才能将其传递到shell

GITHUB_BRANCH:=$(shell echo "$${GITHUB_REF\#refs/heads/}")
值得一提的是,这个简单的参数扩展可以移植到任何合理的现代sh,因此根本不是Bash独有的特性

当然,make完全能够执行相同的替换,而无需调用外部进程

GITHUB_BRANCH := $(patsubst refs/heads/%,%,${GITHUB_REF})

需要注意的是,这是一个bug,将在即将发布的GNU make版本中修复。如果希望在修复错误之前/之后使makefile可移植,则应将其隐藏在如下变量中:

SHELL:=/bin/bash
GITHUB_BRANCH:=$(shell echo "${GITHUB_REF#refs/heads/}")
HASH := \#

foo := $(shell echo "${GITHUB_REF$(HASH)refs/heads/}")

这将适用于所有版本的GNU make。

您是否尝试过定义一个只包含以下内容的make变量?这是一种常用于空间之类的技术。此外,您忘了转义$-应该是${GITHUB\u REFrefs/heads/}您不应该像这样关闭括号吗$shell echo${GITHUB_REF}refs/heads/@Tim No,OP正在尝试使用shell的功能。然后我建议同时转义$,并且通过使用$$和\FWIW,原始的Bourne shell不支持这种扩展语法。看见在ksh88年首次引入IIRC。然而,您很难找到任何工作的UNIX系统,其中/bin/sh实际上是BourneShell,而不是dash、bash等。