以下Makefile / shell / sed行有什么作用?

时间:2012-10-31 04:05:31

标签: shell sed makefile fullcalendar

这一行直接来自FullCalendar(一个jQuery插件)Makefile。我无法理解它,尤其是带有美元符号的部分。我不知道make,shell还是sed“处理”它。我也不清楚其他(显然是?)sed命令。

DEMO_RE = (<script[^>]*_loader\.js[^>]*><\/script>|<!--\[\[|\]\]-->)[^<]*
DEMO_SED = sed -nE '1h;1!H;$${;g;s/${DEMO_RE}//g;p;}'
  1. 1h做什么?
  2. 美元符号和括号在何处以及如何解释?
  3. 第一个g命令和最后一个p命令(打印?)有什么作用?

2 个答案:

答案 0 :(得分:8)

那是一个牛黄。

DEMO_RE是正则表达式。松散地说,这意味着它是对另一个字符序列的描述。任何给定的字符序列都与此正则表达式匹配或不匹配。

DEMO_SED是一个sed命令。在这个阶段,它只是一个Make变量,一个字符序列,但稍后它可以传递给shell(在Make变量扩展之后),它将把它解释为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到达输入的最后一行时才应用此命令(花括号的内容)。 我没有看到领先分号的任何目的,但我不敢说它绝对没有。现在我省略了替换命令的易读性。< / p>

sed -nE '$${;g;p;}'

由于Make尝试扩展以$开头的内容,我们希望传递一个&#39; $&#39;完整到sed,我们用另一个&#39; $&#39;逃脱它。 Make会将$$扩展为$并将${...传递给shell(将其传递给sed)。

sed -nE '1h;1!H;$${;g;p;}'

1h表示将第一行输入复制到保留空间。 1!H表示将第一行以外的每行追加到保留空间。记住-n;在sed执行大括号中的命令组之前不会打印任何内容,只有在读入最后一行输入时才会发生这样的事情。所以:

sed -nE '1h;1!H;$${;g;s/${DEMO_RE}//g;p;}'

&#34;将所有输入读入保留空间,不打印任何内容,然后将其全部拉回到最后,切除与(可能已扩展)相匹配的所有内容,并打印剩余的内容。&# 34;

这个答案变得很长;我可以给你一个关于正则表达式的粗略翻译,但是以一种不会混淆这种媒介的方式这样做是一种痛苦。它似乎想要匹配script标记或<!--[[]]-->所包围的任何内容,以及所有下一个标记的内容。

答案 1 :(得分:3)

Beta在分离sed脚本,逻辑块逻辑块方面做得非常出色。 sed脚本从输入文本中删除某些JavaScript块。他的最终总结可能就是你所需要的。如果你想要一个更短的答案,这里就是。

你提到的令人困惑的是美元符号。

        ┌ Double $ is actually just an "escaped" $ character
        │       ┌ Starts a variable reference
        │       │
'1h;1!H;$${;g;s/${DEMO_RE}//g;p;}'
          │     │        │      │
          │     └variable┘      │
          └ Stuff run at EOF ───┘

第一对美元符号构成一个单一的美元符号,在文件的末尾将其解释为“#34;”。所以外部花括号之间的东西在EOF运行。内部大括号的形式为${VARNAME},这是Make引用变量的方式。它看起来像shell变量引用,但它不是。

在这种情况下,由于Make变量分配实际上并未执行任何操作,因此您的DEMO_SED变量的内容为DEMO_RE。具有讽刺意味的是,原因是这被分成两个变量,分开是为了使整个过程更具可读性。 : - )

请注意,这些执行任何内容(即sed)都不会。它只分配变量。稍后在你的Makefile中,你可能会有一个目标,其行可能类似于:

${DEMO_SED} path/to/file.html.orig > path/to/file.html

在那一点上,所有这些都变成了功能性的东西。