我在 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/sh
isdash
而不是 bash。
有一个简单的修复方法:添加另一个反斜杠来引用反斜杠:
test-makefile:
echo '\\newcommand{\\seance}{seance1}' > seances/seance.tex
请注意,POSIX 标准将 C 反斜杠转义标记echo
为XSI扩展但 POSIX 合规性测试套件的作者声称,它需要符合 XSI 才能符合 POSIX 合规性,除非您只想验证嵌入式使用的小型系统。
由于最初的问题似乎不是针对小型嵌入式系统提出的,因此该系统需要实现 XSI 扩展才能兼容。
请注意,bash
在 Solaris 和 Mac OS 等 POSIX 认证平台上,默认情况下以兼容的方式进行编译echo
。因此,bash 默认情况下不兼容 POSIX XSI 的问题是 Linux 特有的。