在m4中,如何包含名称中包含环境变量的文件?

问题描述:

我想在我的m4文本中包含一个相对于我的沙盒基础目录的文件,而不使用-I开关。在m4中,如何包含名称中包含环境变量的文件?

到目前为止,我已经找到了如何使用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 

如何一个文件的路径中是否包含环境变量?

我认为你需要使用esyscmd而不是syscmdesyscmd读取命令行输出。

+0

你确实是这个人。这工作。谢谢!有趣的是,除了'include'宏调用之外,我可以使用'MODEL_ROOT'。无论如何,谢谢! – 2011-03-17 23:48:55

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

这就是为什么它看起来像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') 

引号会阻止宏的扩展,所以它们不能将它放在此处(您希望将其展开的位置)。引用字符串的其余部分是“恰当的”,因为这不是你想要被宏扩展的东西。


顺便说一句,一个更强大的方式来获得从shell环境变量会是这样的:

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

这将避免因宏名,百分号,反斜杠,水珠问题字符或环境变量值中的空格。这和你的解决方案之间的唯一区别是在变量周围增加了\`\`%s\'\'和引号。

警告:esyscmd将始终将其输出扩展为宏,因此难以保持其真正的消毒效果。即使我使用上面的引号符号,如果这些引号符号存在于环境变量中,它仍然会跳动。