在 Makefile 中,我想打印一个表示为十六进制数的字节,并将其传递给另一个程序的 STDIN。由于某种原因,它不起作用:
without-pipe:
@printf '\x66\x6f\x6f'
with-bash-and-pipe:
@/bin/bash -c "printf '\x66\x6f\x6f' | cat"
with-pipe:
@printf '\x66\x6f\x6f' | cat
运行这个文件会产生:
$ make without-pipe
foo
$ make with-bash-and-pipe
foo
$ make with-pipe
\x66\x6f\x6f
make
我缺少什么功能以及使最后一个目标产生相同输出的正确方法是什么。一个with-bash-and-pipe
是一种解决方法。
注意:我的测试平台是 Ubuntu 18.04.2 LTS。
只需几个步骤即可了解该行为。
1. make有点聪明
看起来
make
确定是否需要 shell。我做了输出的一部分是:
因此,在这种情况下
make
,只需探测printf
(根据$PATH
)的可能位置,直到找到工具。最后一种情况的行为有所不同。这个命令
收益率(除其他外)
该工具足够智能,可以告诉您要运行管道。如果这样做,将使用 shell。外壳是
sh
。2.三种情况使用不同的
printf
实现如上所示,
make without-pipe
使用printf
操作系统中可用的可执行文件。printf
是 bash 中的内置函数(用 确认type -a printf
),因此make with-bash-and-pipe
使用 bash 中的内置函数。printf
也是 sh 的内置函数(用 确认(unset PATH; printf 'printf works\n'; ls)
;如果它不是内置函数,sh 找不到可执行文件,就像它找不到一样ls
),所以make with-pipe
使用 sh 的内置函数。3.
printf
不需要理解\x66
等POSIX 规范
printf
说:两个链接文件都没有说
\xHH
and such must be special。我不确定规范是否明确允许它们是特殊的,但事实是它们对于printf
问题中的某些 -s 是特殊的。但不适用于
printf
sh 中的内置函数。您可以通过指定其完整路径来确保
printf
您运行的不是内置函数:但是,这需要您事先知道路径。要解决此问题,您可以使用
env
:env
将运行在$PATH
. 您可以期望env
在场,因为它是 POSIX 所要求的。另一方面,通常您无法确定任何
printf
可执行文件(内置或非内置)\xHH
首先支持。因此,真正的解决方法是重写您的格式字符串,以便所有符合 POSIX 标准的printf
. 这似乎很有用:例子:
这种方法适用于所有三种情况。