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

时间:2011-03-17 22:36:04

标签: 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

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

2 个答案:

答案 0 :(得分:2)

我认为您需要使用esyscmd代替syscmdesyscmd读取命令行输出。

答案 1 :(得分:1)

正如其他答案所提到的,您必须使用GNU扩展esyscmd才能检索命令的输出。 syscmd宏只是直接打印到stdout,忽略所有宏和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将始终将其输出扩展为宏,因此很难对其进行真正的清理。即使我在上面使用引号符号,如果环境变量中存在这些引号符号,它仍然会跳闸。