Go makefiles中bash命令的使用

Go makefiles中bash命令的使用,bash,macos,go,makefile,Bash,Macos,Go,Makefile,通过命令行(MacOS)使用go run时,可以排除\u test.go文件 但是,通过Go makefile,该命令似乎没有以类似的方式使用。比如说, start: go run $(ls -1 dir/*.go | grep -v _test.go) 及 两者都会导致 go run: no go files listed 在Go makefile中使用grep和类似命令的正确方法是什么?美元符号是特殊的make:它们引入make变量和函数。如果你想在你的食谱中使用字面上的美元符号

通过命令行(MacOS)使用
go run
时,可以排除
\u test.go
文件

但是,通过Go makefile,该命令似乎没有以类似的方式使用。比如说,

start:
    go run $(ls -1 dir/*.go | grep -v _test.go)

两者都会导致

go run: no go files listed

在Go makefile中使用
grep
和类似命令的正确方法是什么?

美元符号是特殊的make:它们引入make变量和函数。如果你想在你的食谱中使用字面上的美元符号,你需要通过加倍来避开它:

start:
        go run $$(ls -1 dir/*.go | grep -v _test.go)

正如在另一个答案中已经提到的,简单的解决方案是将所有美元符号加倍,以防止Make试图将它们解释为Make变量或函数。等效地,您可以使用过时的命令替换语法
`ls。。。用反勾号填充“
,而不是
$(ls…stuff)

然而,这种方法有更根本的缺陷,因为它会陷入影响到整个社会的角落案件的深渊。更可靠的方法是使用Make函数来表示模式

go run $(filter-out %_test.go,$(wildcard dir/*.go))

我还要提到Bash有一个名为extendedglobbing(google
extglob
)的特性,在这里您可以说类似于
!(dir/*_test.go)dir/*.go
从通配符匹配中排除一组文件。但是,当Make具有提供相同功能的内置功能时,您可能不想破坏Makefile的可移植性(尽管语法更为详细。实际上,这是一个特性,因为它使新的维护人员可以很容易地通过谷歌搜索函数名并了解代码的功能!)

您可以使用反勾号而不是
$(ls…
)-在彼此内部使用这两种符号意味着“将
ls
的输出作为命令运行(但这没有发生,因为您仍然需要将美元符号加倍)。如果前缀
dir/
从前面修剪,我想
ls
会这样做…?有一个Make函数
$(notdir…
你可以围绕调用
$(通配符…
我想你已经得到了OP的意图,但从技术上讲,
$(过滤掉%\u test.go,…
并不等同于
grep-v\u test.go
,因为它不捕捉
foo\u test.gobar
,而
grep
捕捉。@RenaudPacalet我认为这是一个特性,而不是一个bug,但是的,你在技术上是正确的,它实际上可能会带来不同。(
grep-v\u test.go
也会删除
it\u testago.go
)我并不反对使用make函数是一个更好的主意,但我不相信它能解决与使用
ls
输出相关的许多问题。毕竟,make不能正确处理包含空格的文件名“两者都可以。确实如此;
make
比shell更挑剔,因此要编写有效的Makefile,需要对文件名施加约束,从而消除解析
ls
输出的许多危险。
start:
        go run $$(ls -1 dir/*.go | grep -v _test.go)
go run $(filter-out %_test.go,$(wildcard dir/*.go))