将命令输出保存到 Makefile 变量时如何保留空格?
How to preserve whitespace when saving command output to a Makefile variable?
我知道像 this one 这样的问题,但我的问题专门针对 makefile,特别是 gnumake。
我有一个命令可以打印换行符和其他空格以标准输出。我想将该输出捕获到一个变量中,然后将该变量打印到一个文件中。
示例生成文件:
OUTPUT=${shell cowsay hello}
all:
@echo "$(OUTPUT)" > output.txt
运行make后,output.txt包含:
_______ < hello > ------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
我希望它保留空格而不是包含:
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
我实际使用的命令不是 cowsay,但它输出类似的空格和换行符。
不幸的是,这是一个否定的答案。 GNU Make Manual states(强调已加):
The shell
function performs the same function that backquotes perform in most shells: it does command expansion. This means that it takes as an argument a shell command and evaluates to the output of the command. The only processing make
does on the result is to convert each newline (or carriage-return / newline pair) to a single space. If there is a trailing (carriage-return and) newline it will simply be removed.
我认为 eval
或 define
没有帮助。
我能看到的唯一解决方法是将 cowsay hello
命令 存储在变量中,而不是命令的输出,如:
OUTPUT=$$(seq 5) # seq 5 replaces cowsay hello
all:
@echo "$(OUTPUT)" > output.txt
如果 cowsay hello
的计算成本很高,或者有副作用,则此变通方法很糟糕。第二种解决方法是保留其输出,但将换行符替换为任意字符,例如使用 sed
,然后将换行符添加回去。例如:
OUTPUT=$(shell seq 5 | sed s/$$/xxx/) # add xxx to the end of each line
all:
@echo -n $(OUTPUT) ' ' | sed 's/xxx /\n/g' # replace xxx-space with line break
I want to capture that output into a variable and then later print the
variable to a file.
似乎没有办法解决 make
将 shell 命令输出中的换行符转换为空格的机制。在将输出分配给变量时,将 shell 转换为一些不常见的字符(如 </code>),然后让它将其翻译回来当 <code>echo
-ing 将该变量写入文件时。像这样:
OUTPUT=$(shell cowsay hello | tr '\n' '')
all:
@echo "$(OUTPUT)" | tr '' '\n' > output.txt
对我来说,这会导致
$ make
$ cat output.txt
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
由于 $(shell)
去除了换行符,只需将它们替换为另一个字符或模式即可。返回 make 后,用换行符替换该字符。
这里我选择了:
作为我的换行符。 YMMV
define \n
endef
cow := $(subst :,${\n},$(shell cowsay hello | tr \n :))
$(error [${cow}])
给予
$ make
Makefile:7: *** [ _______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
]. Stop.
不过您会发现在食谱中使用 ${cow}
很棘手!
Base64编码
我建议你将 cowsay 的输出编码为 base64:
$ cowsay hello
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
$ cowsay hello | base64 -w0
IF9fX19fX18gCjwgaGVsbG8gPgogLS0tLS0tLSAKICAgICAgICBcICAgXl9fXgogICAgICAgICBcICAob28pXF9fX19fX18KICAgICAgICAgICAgKF9fKVwgICAgICAgKVwvXAogICAgICAgICAgICAgICAgfHwtLS0tdyB8CiAgICAgICAgICAgICAgICB8fCAgICAgfHwK
生成文件
cow:
@echo IF9fX19fX18gCjwgaGV.... | base64 -d
make cow
现在只需 运行 make cow
即可正确显示(没有错误的换行符)
$ make cow
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
我知道像 this one 这样的问题,但我的问题专门针对 makefile,特别是 gnumake。
我有一个命令可以打印换行符和其他空格以标准输出。我想将该输出捕获到一个变量中,然后将该变量打印到一个文件中。
示例生成文件:
OUTPUT=${shell cowsay hello}
all:
@echo "$(OUTPUT)" > output.txt
运行make后,output.txt包含:
_______ < hello > ------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
我希望它保留空格而不是包含:
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
我实际使用的命令不是 cowsay,但它输出类似的空格和换行符。
不幸的是,这是一个否定的答案。 GNU Make Manual states(强调已加):
The
shell
function performs the same function that backquotes perform in most shells: it does command expansion. This means that it takes as an argument a shell command and evaluates to the output of the command. The only processingmake
does on the result is to convert each newline (or carriage-return / newline pair) to a single space. If there is a trailing (carriage-return and) newline it will simply be removed.
我认为 eval
或 define
没有帮助。
我能看到的唯一解决方法是将 cowsay hello
命令 存储在变量中,而不是命令的输出,如:
OUTPUT=$$(seq 5) # seq 5 replaces cowsay hello
all:
@echo "$(OUTPUT)" > output.txt
如果 cowsay hello
的计算成本很高,或者有副作用,则此变通方法很糟糕。第二种解决方法是保留其输出,但将换行符替换为任意字符,例如使用 sed
,然后将换行符添加回去。例如:
OUTPUT=$(shell seq 5 | sed s/$$/xxx/) # add xxx to the end of each line
all:
@echo -n $(OUTPUT) ' ' | sed 's/xxx /\n/g' # replace xxx-space with line break
I want to capture that output into a variable and then later print the variable to a file.
似乎没有办法解决 make
将 shell 命令输出中的换行符转换为空格的机制。在将输出分配给变量时,将 shell 转换为一些不常见的字符(如 </code>),然后让它将其翻译回来当 <code>echo
-ing 将该变量写入文件时。像这样:
OUTPUT=$(shell cowsay hello | tr '\n' '')
all:
@echo "$(OUTPUT)" | tr '' '\n' > output.txt
对我来说,这会导致
$ make
$ cat output.txt
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
由于 $(shell)
去除了换行符,只需将它们替换为另一个字符或模式即可。返回 make 后,用换行符替换该字符。
这里我选择了:
作为我的换行符。 YMMV
define \n
endef
cow := $(subst :,${\n},$(shell cowsay hello | tr \n :))
$(error [${cow}])
给予
$ make
Makefile:7: *** [ _______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
]. Stop.
不过您会发现在食谱中使用 ${cow}
很棘手!
Base64编码
我建议你将 cowsay 的输出编码为 base64:
$ cowsay hello
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
$ cowsay hello | base64 -w0
IF9fX19fX18gCjwgaGVsbG8gPgogLS0tLS0tLSAKICAgICAgICBcICAgXl9fXgogICAgICAgICBcICAob28pXF9fX19fX18KICAgICAgICAgICAgKF9fKVwgICAgICAgKVwvXAogICAgICAgICAgICAgICAgfHwtLS0tdyB8CiAgICAgICAgICAgICAgICB8fCAgICAgfHwK
生成文件
cow:
@echo IF9fX19fX18gCjwgaGV.... | base64 -d
make cow
现在只需 运行 make cow
即可正确显示(没有错误的换行符)
$ make cow
_______
< hello >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||