如何在 Makefile Target 中使用 bash 正则表达式

cod*_*ark 4 bash makefile gnu-make

在 bash 脚本中,以下正则表达式似乎运行良好:

MY_STRING="FirstName-LastName-Gender-Age"
MY_REGEX="([^-]+)-([^-]+)$"
if [[ $MY_STRING =~ $MY_REGEX ]]; then
    echo "Match: $BASH_REMATCH"
fi
Run Code Online (Sandbox Code Playgroud)

我有兴趣在 Makefile 中使用这个脚本。它似乎存在语法问题。例如:

my-target:
    MY_STRING="FirstName-LastName-Gender-Age"
    MY_REGEX="([^-]+)-([^-]+)$"
    if [[ $MY_STRING =~ $MY_REGEX ]]; then
        echo "Match: $BASH_REMATCH"
    fi
Run Code Online (Sandbox Code Playgroud)

make 中正确的语法是什么?上面的代码似乎存在变量赋值问题、正则表达式中的“$”问题等。

Mad*_*ist 5

你这里有很多问题。第一个是 make 不调用 bash 作为其 shell,而是调用/bin/sh(POSIX shell)。在许多系统上,它是 bash 的链接,但在许多其他系统上,它是 dash 或其他 POSIX shell 的链接。如果你尝试在你的 makefile 配方中使用像这样的 bash-isms,你的 makefile 是不可移植的。如果您愿意,您可以添加SHELL := /bin/bash到 makefile 中以强制 make 始终使用 bash...但在 bash 不可用的任何地方它都会失败。

第二个问题是 make 在单独的 shell 中调用配方的每个逻辑行。按照您编写的方式,每个变量赋值都是在新 shell 中创建的,然后 shell 退出并且该赋值会丢失。此外,只有 if 语句的第一行被发送到 shell,这显然是一个语法错误。您需要在换行符之前使用反斜杠,以确保整个脚本是一个逻辑行并发送到同一个 shell...这意味着您还需要添加分号来在需要的地方换行。

即使在 shell 脚本中, 的 赋值MY_REGEX也是可疑的,因为双引号字符串中有未转义的美元符号。然而它恰好适合你,因为美元符号后面没有可以作为变量的字符。尽管如此,为了安全起见,您应该在此处使用单引号字符串。

最后,美元符号 ( $) 是特殊制作的,所以如果你想将 a 传递$给 shell,你必须转义它。Make 使用两个美元符号$$来转义单个美元符号。

所以,你的 makefile 应该是这样的:

SHELL := /bin/bash

my-target:
        MY_STRING="FirstName-LastName-Gender-Age"; \
        MY_REGEX='([^-]+)-([^-]+)$$'; \
        if [[ $$MY_STRING =~ $$MY_REGEX ]]; then \
            echo "Match: $$BASH_REMATCH"; \
        fi
Run Code Online (Sandbox Code Playgroud)

就我个人而言,我会重写它以使用标准工具而不是依赖 bash 等,但这是你的决定。