使用 fgrep 在 makefile 中出现意外的 perl 正则表达式替换输出

Unexpected perl regex substitution output in makefile using fgrep

prwhite 在 GitHub

上的这条规则的启发
help:
    @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\$$//' | sed -e 's/##//'`

我正在尝试制作一个用空格替换目标文件的版本。我想用所有空格替换字符串的一部分。 使用文件 input.txt

spec: $(ALL_FILES)      ## Runs all specs
myst-spec: $(ALL_FILES) ## Runs just the in-language specs
build: $(SOURCE_FILES)   ## Builds myst into an executable
check: $(ALL_FILES)     ## Runs all crystal specs
clean:                  ## Cleans (deletes) docs and executables
help:                   ## Show this help.

这是预期的输出:

spec:                   ## Runs all specs
myst-spec:              ## Runs just the in-language specs
build:                  ## Builds myst into an executable
check:                  ## Runs all crystal specs
clean:                  ## Cleans (deletes) docs and executables
help:                   ## Show this help.

这是我目前的规则:

help:
    @fgrep -h "##" input.txt | fgrep -v fgrep | \
      perl -pe 's/(.*):(.*)##(.*)/(":" . (" " x length()) . " ")/e'

注意这里使用了fgrep,因为实际上这应该是makefile本身的运行,但我在这里使用input.txt所以你不必处理与整个生成文件。

没想到,我得到了这个输出:

:
:
:
:
:
:

最让我困惑的是,如果我直接在 input.txt 上 运行 perl 脚本(像这样:cat input.txt | perl -pe 's/(.*):(.*)##(.*)/(":" . (" " x length()) . " ")/e')——我得到了预期的输出。它给出不同输出的原因是什么?我意识到它(可能)与 fgrep 有关,但我不明白它会有什么不同,所以我来了。

如果你想在食谱中使用 $,你必须将它加倍到 $$

help:
    @fgrep -h "##" input.txt | fgrep -v fgrep | \
      perl -pe 's/(.*):(.*)##(.*)/("$:" . (" " x length($)) . " $")/e'

以上可以简化:

help:
    @perl -ne'next if !/##/; s/(.*):(.*)##(.*)/ "$:".( " " x length($) )." $" /e; print'

或 (5.10+):

help:
    @perl -ne'next if !/##/; s/:\K(.*)(?=##)/ " " x length($) /e; print'