在configure.ac中为变量赋值

编程语言 2026-07-09

打开终端时,我可以执行:

igor@IgorReinCloud \~/dbhandler $ set | grep SQLANY\[09\]\*  
SQLANY17=/opt/sqlanywhere17  
SQLANYSAMP17=/opt/sqlanywhere17/samples  
igor@IgorReinCloud \~/dbhandler $

但在 configure.ac 内执行以下操作时:

SQLANY=\`set | grep "SQLANY\[09\]\*"\`  
AC_MSG_NOTICE(\[Variable is $SQLANY\])

并重新生成/重新运行configure我得到:

Variable is

我到底做错了什么?

我的目标是得到 Variable is SQLANY17=/opt/sqlanywhere17,然后使用 awk 来解析该值以获取目录。

我无法控制导出的名称,因此需要以某种方式获取路径。 17 那里有版本号,因此我在寻找一个通用的解决方案,使其适用于任意版本。

解决方案

请始终记住,Autoconf的主要工作是生成 configure,它是一个shell脚本。如果 configure 没有按预期工作,你总是有选项直接对其进行调试。你通常会看到大量与Autoconf宏相关的代码,但你的模板文本以及周围生成的代码,应该可以通过文本编辑器的搜索功能不难找到。

当我给它这组来自问题的输入时……

AC_INIT([so_test], [0.0.1])
SQLANY=\`set | grep "SQLANY\[09\]\*"\`
AC_MSG_NOTICE([Variable is $SQLANY])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Autoconf生成了一个 configure 脚本,里面包含了相应的代码(以及更多):

SQLANY=\`set | grep "SQLANY\09\\*"\`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Variable is $SQLANY" >&5
printf "%s\n" "$as_me: Variable is $SQLANY" >&6;}
ac_config_files="$ac_config_files Makefile"

运行它产生了以下输出:

grep: warning: stray \ before 0 configure: Variable is configure: creating ./config.status config.status: creating Makefile

,且来自 grep 的信息输出到标准错误,其他信息输出到标准输出。再多做一点实验可以确认你可能预期的那样,当模式解析像那样失败时,grep 不会向标准输出输出任何内容。

这里有几件事在同时发生,但最重要的是,在Autoconf中,成对的方括号([])是引用定界符。反斜杠(\)对Autoconf / M4并不特殊。Autoconf中的引用是一个比人们想象的还要复杂的话题,因此我建议你阅读 Autoconf手册的相关章节

其次,你尝试使用的实际命令还有一些问题,至少包括

  • 你应该偏好现代(有点儿类似的)POSIX命令替换语法。这适用于你所有的脚本和交互式命令,不仅仅是Autoconf的输入。这有若干好处,而且现在也不再算新鲜事。
  • 正则表达式 SQLANY[09]* 并不等同于你以为它表示的含义。在你的例子中,它只匹配输入的 SQLANY 部分,而不是数字。你很可能需要 SQLANY[0-9]{1,},它在字母之后至少需要一个十进制数字,并且接受从 09 的数字,而不仅仅是端点。
  • 我建议在shell代码中使用单引号来进行引用,除非你有充分的理由另作处理,比如你想要变量插值或字面量单引号字符。

总之,这对我有用,而且是我会推荐的写法

[SQLANY=$(set | grep -E 'SQLANY[0-9]{1,}')]
AC_MSG_NOTICE([Variable is $SQLANY])

这类写法有很多可能的变体,尤其是在变量赋值中哪些部分是用m4引号括起来,以及 grep 命令的确切形式,但我喜欢这一种,因为它清晰、符合良好的shell风格,并且避免GNU的特定特性。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章