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

Max*_*Max 3 shell makefile sed 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;}'
Run Code Online (Sandbox Code Playgroud)
  1. 1h做什么?
  2. 美元符号和括号在何处以及如何解释?
  3. 第一个g命令和最后一个p命令(打印?)有什么作用?

Bet*_*eta 8

那是一个牛黄.

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

DEMO_SED是一个sed命令.在这个阶段,它只是一个Make变量,一个字符序列,但稍后它可以传递给shell(在Make变量扩展之后),它将把它解释为sed命令.

我并不完全理解这个sed命令,但这是我最好的尝试.从中间开始:

sed 's/${DEMO_RE}//'
Run Code Online (Sandbox Code Playgroud)

Make将扩展${DEMO_RE}为第一行中的gobbledegook字符串,查找正在考虑的任何文本行的匹配项,并将匹配的文本更改为空(即删除它).

sed 's/${DEMO_RE}//g'
Run Code Online (Sandbox Code Playgroud)

命令的g修饰符s意味着对所有匹配进行替换(在本例中为删除),而不仅仅是找到的第一个匹配.

sed -nE 's/${DEMO_RE}//g;p'
Run Code Online (Sandbox Code Playgroud)

-n默认情况下,均值不会打印结果.该p方法打印模式空间的内容,所以目前这些更改相互抵消.该E方法将正则表达式解释为扩展正则表达式,而不是基本正则表达式

sed -nE '{s/${DEMO_RE}//g;p}'
Run Code Online (Sandbox Code Playgroud)

花括号将这些命令组合在一起.

sed -nE '${;g;s/${DEMO_RE}//g;p;}'
Run Code Online (Sandbox Code Playgroud)

现在事情变得复杂了.Sed有一个叫做保持空间的第二个缓冲区.该g命令将保留空间的内容复制到模式空间(这是人们通常使用的缓冲区,也是大多数人都知道的唯一缓冲区).在我们考虑将事物放入保留空间的其他命令之前,这没有多大意义.这$意味着只有当sed到达输入的最后一行时才应用此命令(花括号的内容).我没有看到领先分号的任何目的,但我不敢说它绝对没有.现在我将省略替换命令的易读性.

sed -nE '$${;g;p;}'
Run Code Online (Sandbox Code Playgroud)

由于Make尝试从头开始扩展$,我们希望将'$'原封不动地传递给sed,我们用另一个'$'来逃避它.请将扩大$$$并传递${...到外壳(将它传递给SED).

sed -nE '1h;1!H;$${;g;p;}'
Run Code Online (Sandbox Code Playgroud)

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

sed -nE '1h;1!H;$${;g;s/${DEMO_RE}//g;p;}'
Run Code Online (Sandbox Code Playgroud)

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

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

  • "前导"分号实际上是花括号和以下命令之间的分界线.GNU sed并不需要它,但几乎所有其他sed实现都需要它.应始终包含它以便于移植. (2认同)