4

我想在我的 m4 文本中包含一个相对于我的沙箱基目录的文件,而不使用-I开关。

到目前为止,我已经弄清楚了如何使用 sys 调用来获取环境变量:

define(MODEL_ROOT,`syscmd(`printf $MODEL_ROOT')')dnl

接下来,我想包含一个基于该环境变量的文件:

include(MODEL_ROOT/sw/lib/m4_macros/foreach2.m4)

总的来说,我有:

define(MODEL_ROOT,`syscmd(`printf $MODEL_ROOT')')

MODEL_ROOT

MODEL_ROOT/sw/lib/m4_macros/foreach2.m4

include(MODEL_ROOT/sw/lib/m4_macros/foreach2.m4)

哪个打印:

/home/ross/sandbox

/home/ross/sandbox/sw/lib/m4_macros/foreach2.m4

/home/ross/sandboxforeach_example.m4:7: m4: Cannot open /sw/lib/m4_macros/foreach2.m4: No such file or directory

我知道包含的正常语法是

include(`file.m4')

但是如果我引用MODEL_ROOT/sw/lib/m4_macros/foreach2.m4,那么 m4 就像:

[...]
include(`MODEL_ROOT/sw/lib/m4_macros/foreach2.m4')

m4 抱怨:

[...]
foreach_example.m4:7: m4: Cannot open MODEL_ROOT/sw/lib/m4_macros/foreach2.m4: No such file or directory

如何在其路径中包含具有环境变量的文件?

4

2 回答 2

4

我认为您需要使用esyscmd而不是syscmd. esyscmd读取命令行输出。

于 2011-03-17T23:31:03.220 回答
1

正如其他答案所提到的,您必须使用 GNU 扩展esyscmd才能检索命令的输出。syscmd宏只是直接打印到标准输出,忽略所有宏和s divert

这就是为什么它看起来MODEL_ROOT在其他任何地方都可以工作:确实如此,但仅在 m4 不需要处理其输出的非常简单的情况下。

但是,关于引用:

  • include(MODEL_ROOT/sw/lib/m4_macros/foreach2.m4)
  • include(`MODEL_ROOT/sw/lib/m4_macros/foreach2.m4')

这应该移动引号:

include(MODEL_ROOT`/sw/lib/m4_macros/foreach2.m4')

引号防止MODEL_ROOT宏的扩展,因此它们不能将它包含在此处(您希望它被扩展的地方)。引用字符串的其余部分是“正确的”,因为它不是您希望通过宏扩展的东西。


顺便说一句,从 shell 获取环境变量的更可靠的方法是:

define(`HOME', esyscmd(`printf \`\`%s\'\' "$HOME"'))

这将避免由宏名称、百分号、反斜杠、全局字符或环境变量值中的空格引起的问题。这与您的解决方案之间的唯一区别是\`\`%s\'\'在变量周围添加和引号。

一个警告:esyscmd它的输出总是会扩展为一个宏,所以很难保持它的真正净化。即使我在上面使用引号符号,如果这些引号符号存在于环境变量中,它仍然会出错。

于 2016-08-01T08:45:47.820 回答