bash/debian:奇怪的 makefile 行为

bash/debian:奇怪的 makefile 行为

我在 TeX 中使用一个非常简单的 makefile:

test-makefile:
    echo '\newcommand{\seance}{seance1}' > seances/seance.tex

我运行它:

$ make test-makefile 
echo '\newcommand{\seance}{seance1}' > seances/seance.tex

我的问题是,在名为“seances”的文件夹中创建的文件不包含它应包含的前两个字符:


ewcommand{\seance}{seance1}

它的第一行是空的。

当然,我可以保护第一个反斜杠:echo '\\newcommand{\seance}{seance1}等。但在现实世界中它不起作用:我真正的 makefile(我已经发布了 ECM)不起作用。

会发生什么? bash/debian 怎么会误解命令的开头呢?



顺便一提:

$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
$ cat /etc/debian_version
buster/sid
$ uname -a
Linux giljourdan 4.16.0-1-amd64 #1 SMP Debian 4.16.5-1 (2018-04-29) x86_64 GNU/Linux

答案1

echo是那些解释者之一反斜杠转义。 A\n表示换行符,所以你就明白了。后一个反斜杠按原样出现,因为\s不是有效的转义代码。

Make 通过 shell 运行命令,/bin/sh默认使用,在 Debian 上使用 dash。 Dash 的内置函数echo确实处理反斜杠。 Bash 没有。 (Debian 上的外部也不重要/bin/echo,除非你明确运行/bin/echo)。

最好的选择是显式使用printf,它至少是安全的,因为它总是处理反斜杠转义符。下面应该总是做同样的事情,\\n在开始时产生一个真正的反斜杠和一个n\n后者产生一个换行符来结束该行。

foo:
        printf '\\newcommand\n' > foo

(或者,如果你想避免处理反斜杠,然后使用printf "%s" '\newcommand')

查看问题为什么 printf 比 echo 更好?有关陷阱的更多详细信息echo

答案2

您的echo程序符合 POSIX 标准并扩展了 C 反斜杠转义。这很可能是因为/bin/shisdash而不是 bash。

有一个简单的修复方法:添加另一个反斜杠来引用反斜杠:

 test-makefile:
        echo '\\newcommand{\\seance}{seance1}' > seances/seance.tex

请注意,POSIX 标准将 C 反斜杠转义标记echoXSI扩展但 POSIX 合规性测试套件的作者声称,它需要符合 XSI 才能符合 POSIX 合规性,除非您只想验证嵌入式使用的小型系统。

由于最初的问题似乎不是针对小型嵌入式系统提出的,因此该系统需要实现 XSI 扩展才能兼容。

请注意,bash在 Solaris 和 Mac OS 等 POSIX 认证平台上,默认情况下以兼容的方式进行编译echo。因此,bash 默认情况下不兼容 POSIX XSI 的问题是 Linux 特有的。

相关内容