无法在 Makefile 上使用 if egrep 转换 bash 脚本

Cannot convert bash script with if egrep on Makefile

我要转换执行

if egrep -r 'my_pattern' ./template_builder
then exit 1
elif egrep -r 'my_second_pattern' ./template_builder
then exit 1
fi

在 Makefile 中,暂时没有成功。

构建这个:

cd /tmp;
mkdir template_builder;
echo "not_pattern" >> ./template_builder/test.txt
# Do the command at the top, nothing happens
echo "my_pattern" >> ./template_builder/test.txt
# Do the command at the top, terminal stops

touch Makefile 

在 Makefile 中,我认为这会起作用:

check:
    if egrep -r 'my_pattern' ./template_builder
    then exit 1
    elif egrep -r 'my_second_pattern' ./template_builder
    then exit 1
    fi
make check
if egrep -r 'my_pattern' ./template_builder
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [template] Error 2

我该如何解决这个问题?

如果我没理解错的话,如果位于/tmp的目录template_builder不包含匹配字符串'my_pattern''my_second_pattern'的文件,你想退出来自 make,带有错误代码。

您可以使用 Makefile 中的此规则实现此目的:

check:
        egrep -r -v 'my_pattern' /tmp/template_builder || egrep -r -v 'my_second_pattern' /tmp/template_builder

解释:第一个 egrep 会 return 一个错误,如果他找到一个匹配。由于 || 运算符的存在,第二个 egrep 将被调用。第二个命令的结果将是 make 将看到的结果。如果它 return 是一个错误,make 的执行将被中止,这似乎是您所期望的行为。

注意:我编辑了我的答案。正确的布尔运算符是 || 而不是 &&.

您的尝试离成功不远了!

在每一行的末尾添加反斜杠,并且 ;s 作为明确的命令分隔符(当然使用真正的制表符而不是下面的 8-space 缩进):

check:
        if egrep -r 'my_pattern' ./template_builder; \
        then exit 1; \
        elif egrep -r 'my_second_pattern' ./template_builder; \
        then exit 1; \
        fi

正如其他人已经指出的那样,make 在新的 shell 子流程中运行配方中的每一行。 (为了记录,它使用开箱即用的 sh,而不是 Bash。)简单的修复是添加一个反斜杠以转义每行末尾的换行符,这应该在同一行执行shell 作为下一个。 (你还需要在某些地方添加分号,比如在 thenelsefi 之前。)但是你真的想重构使用 [=13 的设施和习语=].

make 的默认逻辑是在任何一行失败时终止配方。因此,您的代码可以简化为

check: template_builder
    ! egrep -r 'my_pattern' $<
    ! egrep -r 'my_second_pattern' $<

这里不需要明确的 exit 1(否定零退出代码会产生这样的结果);但是如果你想强制执行一个特定的退出代码,你可以用

    egrep -r 'my_pattern' $< && exit 123 || true

现代 POSIX 比传统 egrep 更喜欢 grep -E;当然,对于这些简单的模式,您可以只使用 grep,甚至 grep -F (née fgrep).

此外,如果您想在同一组文件中搜索这两种模式,一次搜索它们会更有效率。

check: template_builder
    ! egrep -e 'my_pattern' -e 'my_second_pattern' -r $<

... 或将它们组合成一个正则表达式 my_(second_)?pattern(需要 egrep / grep -E)。

另请注意我是如何将依赖关系分解为 $< 并使其明确的;但是你可能想要制作这个食谱 .PHONY,这样即使没有任何改变它也会被执行。

(你不能直接 copy/paste 这段代码,因为 Stack Overflow 愚蠢地将 markdown 源中的文字标签呈现为空格。)