那是相当牛黄。
DEMO_RE
是一个正则表达式。粗略地说,这意味着它是对另一个字符序列的描述。任何给定的字符序列要么匹配此正则表达式,要么不匹配。
DEMO_SED
是一个 sed 命令。在这个阶段,它只是一个 Make 变量,一个字符序列,但稍后可以将其传递给 shell(在 Make 变量扩展之后),shell 会将其解释为 sed 命令。
我不完全理解这个 sed 命令,但这是我最好的尝试。从中间开始:
sed 's/${DEMO_RE}//'
Make 将扩展${DEMO_RE}
为第一行中的 gobbledegook 字符串,查找与正在考虑的任何文本行的匹配,并将匹配的文本更改为空(即删除它)。
sed 's/${DEMO_RE}//g'
命令的g
修饰符s
意味着对所有匹配项进行替换(在本例中为删除),而不仅仅是找到的第一个匹配项。
sed -nE 's/${DEMO_RE}//g;p'
该-n
方法默认情况下不打印结果。该p
方法打印模式空间的内容,因此目前这些更改相互抵消。该E
方法将正则表达式解释为扩展的正则表达式,而不是基本的正则表达式。
sed -nE '{s/${DEMO_RE}//g;p}'
花括号将这些命令分组。
sed -nE '${;g;s/${DEMO_RE}//g;p;}'
现在事情变得复杂了。Sed 有第二个缓冲区,称为保持空间。该g
命令将保持空间的内容复制到模式空间(这是人们通常使用的缓冲区,也是大多数人知道的唯一一个)。在我们考虑将把东西放入保持空间的其他命令之前,这没有多大意义。这$
意味着仅当 sed 到达输入的最后一行时才应应用此命令(大括号的内容)。我认为前导分号没有任何用途,但我不敢说它绝对没有任何作用。现在,为了便于阅读,我将省略替换命令。
sed -nE '$${;g;p;}'
由于 Make 尝试扩展以 开头的内容$
,并且我们想将 '$' 原封不动地传递给 sed,因此我们用另一个 '$' 对其进行转义。Make 将扩展$$
并$
传递${...
给 shell(它将传递给 sed)。
sed -nE '1h;1!H;$${;g;p;}'
这1h
意味着将输入的第一行复制到保持空间。该方法将除第一行之外1!H
的每一行附加到保留空间。记住; 在 sed 执行花括号中的命令组之前不会打印任何内容,这只会在读入最后一行输入时发生。所以:-n
sed -nE '1h;1!H;$${;g;s/${DEMO_RE}//g;p;}'
“将所有输入读入保留空间,不打印任何内容,然后在最后将其全部拉回,切除与(可能扩展的)匹配的所有内容,并打印剩下的所有内容。”
这个答案变得很长;我可以给你一个正则表达式的粗略翻译,但是以一种不会混淆这个媒介的方式这样做是一种痛苦。它似乎想要匹配任何被script
标签 or<!--[[
包围的东西]]-->
,以及所有这些都跟随到下一个标签。