我想在不使用-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
如何在路径中包含环境变量的文件?
答案 0 :(得分:2)
我认为您需要使用esyscmd
代替syscmd
。 esyscmd
读取命令行输出。
答案 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
将始终将其输出扩展为宏,因此很难对其进行真正的清理。即使我在上面使用引号符号,如果环境变量中存在这些引号符号,它仍然会跳闸。