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

在m4中,如何包含名称中包含环境变量的文件?,m4,M4,我想在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_

我想在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
我知道includes的正常语法是

include(`file.m4')
但是如果我引用
MODEL\u ROOT/sw/lib/m4\u 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
而不是
syscmd
esyscmd
读取命令行输出。

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

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

然而,关于引用:

  • 包括(MODEL\u ROOT/sw/lib/m4\u macros/foreach2.m4)
  • include(`MODEL\u ROOT/sw/lib/m4\u macros/foreach2.m4')
这将移动引号:

include(MODEL_ROOT`/sw/lib/m4_macros/foreach2.m4')
引号防止扩展
MODEL\u ROOT
宏,因此不能将其括在此处(您希望将其展开的位置)。引用字符串的其余部分是“合适的”,因为您不希望用宏来扩展它


另一方面,从shell获取环境变量的更健壮的方法如下:

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


需要注意的是:
esyscmd
总是将其输出扩展为宏,因此很难对其进行真正的消毒。尽管我在上面使用了引号符号,但如果环境变量中存在这些引号符号,它仍然会出错。

您确实就是那个人。成功了。谢谢奇怪的是,除了在
include
宏调用中,我实际上可以使用
MODEL\u ROOT
。无论如何,谢谢!