Joh*_*nes 13 shell bash make process-substitution
在 bash 提示符下,可以使用伪文件执行 diff:
diff <(echo test) <(echo test)
Run Code Online (Sandbox Code Playgroud)
将其按原样添加到 Makefile 失败:
all:
diff <(echo test) <(echo test)
Run Code Online (Sandbox Code Playgroud)
错误(提示:/bin/sh 指向此系统上的 /bin/bash):
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `diff <(echo test) <(echo test)'
Run Code Online (Sandbox Code Playgroud)
这是什么意思,有没有办法在不使用临时文件的情况下仍然区分两个输出?
Kus*_*nda 23
/bin/sh可能bash在您的系统上,但是当作为 调用时sh,bash将以 POSIX 模式运行(就像POSIXLY_CORRECT已定义或以 开头--posix)。
在这种模式下,不存在进程替换。
解决方案:
使用显式临时文件:
all:
command1 >tmpfile
command2 | diff tmpfile -
rm -f tmpfile
Run Code Online (Sandbox Code Playgroud)
使用bash -c内嵌脚本:
all:
bash -c 'diff <(command1) <(command2)'
Run Code Online (Sandbox Code Playgroud)
将 Makefile 变量定义SHELL为/bin/bash(或系统上的任何路径bash):
SHELL=/bin/bash
Run Code Online (Sandbox Code Playgroud)
如果您想要便携性,请使用第一个解决方案。如果您可以依赖于bash,请选择第二个。如果您另外不需要关心非 GNUmake实现,请使用第三个。
关于设置SHELL:POSIX 标准规定,Makefile 中的可执行文件应通过system()C 库函数调用make。此函数不保证使用SHELL环境变量(事实上,标准不鼓励这样做)。该标准还详细说明设置 Makefile 变量SHELL不应影响环境变量 SHELL。make然而,在我所知道的大多数实现中,Makefile 变量SHELL将用于执行命令。
该实用程序的基本原理中make的建议是使用bash -c:
省略
MAKESHELL了其他make实现提供的历史特性和相关特性。在某些实现中,它用于让用户覆盖用于运行make命令的 shell 。这令人困惑;对于可移植的make,shell 应该由 makefile 编写者选择。此外,makefile 编写器不能要求使用备用 shell 并且仍然认为 makefile 可移植。虽然可以标准化指定备用 shell 的机制,但现有实现不同意这种机制,并且 makefile 编写者已经可以通过在目标规则中指定 shell 名称来调用备用 shell;例如:
python -c "foo"