【问题标题】:I am trying to define a string X="either 'this|that'" but GNU make won't accept it我正在尝试定义一个字符串 X="either 'this|that'" 但 GNU make 不会接受它
【发布时间】:2017-03-03 23:12:29
【问题描述】:

我正在尝试为 GNU make 编写一个 Makefile。我无法弄清楚这里的问题是什么:

foo := this|works
bar := "I lost my 'single quotes'"
baz := 'make|will|not|accept|this|with|the|single|quotes'

whatIWant := "A string with its 'single|quoted|regex|alternatives'"

this-almost-works:  #But the single quotes are lost.
        @printf '%s ' "$(whatIWant)"

this-fails-horribly:
        @printf '$(whatIWant)'

我收到以下错误消息

/bin/sh: 1: quoted: not found
/bin/sh: 1: /bin/sh: 1: regex: not foundalternatives": not found

blah blah Error 127
  1. 为什么它试图在 shell 中运行这个字符串的一部分?

  2. 如何定义一个变量以准确包含 whatIWant 的内容?

【问题讨论】:

  • 用 '\' 转义你的管道,如果我没记错的话,管道是 makefile 中的特殊字符
  • 酷。这有助于避免错误消息。虽然我真的不明白为什么 foo 有效而 baz 无效。我仍然需要保留那些单引号。由于某种原因,它们消失了。
  • Make 不解释引号,它们在字符串中。所以实际上你在这里做的是:@printf '%s ' ""A string with its 'single|quoted|regex|alternatives'"" 用引号解释,所以'single|quoted|regex|alternatives' 丢失它的引号,因为它是一个带引号的字符串。这有意义吗?
  • 管道在 makefile 中是 not 特殊字符,除了在 GNU make 先决条件列表中,它们将正常先决条件与仅订购先决条件分开。它们对 shell 来说是特殊的,但不在引号内(任何一种类型)。

标签: makefile gnu-make


【解决方案1】:

可能值得详细了解扩展。

定义变量时, 几乎唯一有影响的角色是$。 其他一切都按字面意思理解。 忽略赋值运算符(=:=)周围的空白是毫无价值的。

foo  :=     this|works

foo 被分配了文字文本this|works。 同样,

baz := 'make|will|not|accept|this|with|the|single|quotes'

将文字文本'make|will|not|accept|this|with|the|single|quotes' 分配给baz。 很好,花花公子。

现在,当 make 决定构建 this-fails-horribly (可能是因为你对shell说make this-fails-horribly) 它在执行任何操作之前扩展命令块。 不无道理, $(whatIWant) 替换为 "A string with its 'single|quoted|regex|alternatives'"。 再次,很好,花花公子。 剩下的将逐字逐句传递给 shell。 外壳看到

printf '"A string with its 'single|quoted|regex|alternatives'"'

(如果您省略了 @ 前缀,那么 make 会对您有所帮助)。 现在我们进入了 shell 引用的领域。

  • printf 命令传递一个参数:"A string with its single
    • '"A string with its ' 是一个单引号字符串。 shell 去除了's 并留下了文本"A string with its
    • single 中没有元字符,因此 shell 不理会它。
  • 输出通过管道传送到quoted 命令
  • 输出通过管道传送到regex 命令
  • 输出通过管道传送到alternatives" 命令
    • shell 看到单引号字符串'=',去掉引号,留下文字=,它附加到单词alternatives

没有语法错误。 当 shell 尝试设置管道时,它会查找 alternatives" 命令。 它在其$PATH 的目录中找不到一个,因此它以消息/bin/sh: 1: /bin/sh: 1: regex: not foundalternatives": not found 停止。

一种可能的编码方式:

.PHONY: this-workes-nicely
this-workes-nicely:
    echo $(whatIWant)

虽然您可能会发现首先将引号留在变量定义之外更简洁。

【讨论】:

  • 感谢您详细解释。 printf 的全部目的是为了调试,所以我特别感谢“@”抑制了我试图得到的确切消息的评论。
猜你喜欢
  • 2015-07-02
  • 2019-04-26
  • 1970-01-01
  • 2020-02-20
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 2021-05-10
  • 1970-01-01
相关资源
最近更新 更多