【问题标题】:Regex to remove block comments also removing * selector正则表达式删除块注释也删除 * 选择器
【发布时间】:2015-07-24 13:19:26
【问题描述】:

我正在尝试使用 bash 从 .css 文件中删除所有块 cmets。我有以下 sed 命令的正则表达式:

sed -r '/\/(\*)*(\s)?(\w)*|(\*)(\s)?(\w)*/d'

这可以很好地剥离块 cmets,例如:

/**
* This is a comment
*/

/* this is another comment */

但它也删除了 * Selector 的实例

* { 
     font-size: 10px;
     ...etc
  }

如何更改当前的正则表达式以考虑这种特殊情况?还是我需要重写我的正则表达式?

编辑: 澄清一下,我将遇到的 cmets 类型:

/**
* This is a comment
*/

/* This is another comment */

/* This is also 
valid
*/

/** "*/" as is { this } */

【问题讨论】:

  • 一定要带sed吗?
  • 最好,但我愿意接受建议,我愿意阅读 awk 或其他任何内容
  • /** "*/" as is { this } */:即使*/ 用双引号括起来,它也总是被视为一个结束序列。所以评论部分是/** "*/

标签: regex linux bash unix sed


【解决方案1】:

以下sed 命令应该适合您:

sed '/\/\*\**/{:a;/\*\//d;N;ba}' file.css

该命令搜索模式/**/*,如果找到,它将执行大括号{cmd1;cmd2;...} 之间的命令块。在该块中,我首先定义了一个标签:a。在下一个命令中,我检查模式缓冲区是否包含关闭的*/。如果找到,我删除模式缓冲区并开始下一个循环。否则,我通过N 将下一行输入附加到模式缓冲区,并通过ba 转到标签a

file.css:

/**
* This is a comment
*/
a {
    font-size: 10px;
}

/* This is another comment */
li {
    font-size: 12px;
}

/* This is also 
valid
*/
* {
    color:white;
}

/** "*/" as is { this } */
table {
    color:blue;
}

输出:

a {
    font-size: 10px;
}

li {
    font-size: 12px;
}

* {
    color:white;
}

table {
    color:blue;
}

【讨论】:

  • 留下/* this is another comment */ 行,需要删除* ,sed '/\/\*/{:a;/\*\//d;N;ba}'
  • 击败我吧,它保留了 * 选择器,但也保留了单行 cmets,例如 /* comment */
  • 它没有保留单行 cmets,它只保留了以 /* 开头的 cmets,而不是 /**。我是故意这样做的,因为你在你的问题中说了这一点。编辑它
  • @hek2mgl 什么是 :a; N;ba 部分的正则表达式在做什么?如果您可以在网站上指出一个体面的指南,则无需详细解释
  • \** 使* 可选,您应该删除量词\*
【解决方案2】:

使用 awk

awk '!/\/?\*/||/{/'  file

说明

!/\/?\*/ 

! 表示没有 // 包含正则表达式 \/? 0 或 1 个正斜杠,需要转义,因为 / 是正则表达式的分隔符 \*文字*

整体匹配不以/*开头的行

||

或用于将语句链接在一起的命令,如果第一个命令失败,它将短路并且不执行第二个(但这里不相关)

/{/

如果该行包含左括号,则执行命令块

没有命令方块,默认动作是打印。

因此,作为一个整体,命令'!/^\/?\*/||/{/' 表示如果该行不包含/**,或者它包含{,则打印该行。


如果 cmets 包含 {

awk '/\/\*/{x=1}!x;/\*\//{x=0}' file

说明

这个检查行有/*并将x设置为1。 !x 表示如果 x 为 0 或 null,则打印该行。它打印,因为它没有动作块。 当遇到*/ 时,x 被设置回 0。


输出

* {
     font-size: 10px;
     ...etc
  }

不考虑引用的内容,例如 /* "*/" hello i'm still comment


什么时候会坏

COMMAND

awk '!/\/?\*/||/{/'

FILE

/*
I am comment that will print
*/

...

COMMAND

awk '/\/\*/{x=1}!x;/\*\//{x=0}'

FILE

/*
I wont print "*/"
I will print as the "*/" is seen as the end of the comment
This line prints
*/ ## This line will also print at x has not been set back to one

【讨论】:

  • 我会删除^。否则它只会删除从行首开始的 cmets。
  • @hek2mgl 可以* 不会出现在文件中的其他任何地方并且不是评论吗?
  • 可能有类似 scss .leftNav{ width: 300px / 960px * 100%;但我认为我正在处理这不应该是一个问题
  • @jbailie1991 可能最好使用第二个命令。我假设这就是 cmets 的工作原理?
  • 在我正在处理的一些文件中很少出现这种情况,并且以这种风格创建了测试 cmets,它也适用于这些文件。顺便说一句,我输入了一个测试注释: /* "*/" valid */ 如果那是您在输出段末尾的意思是什么类型的注释,它也会将其删除
【解决方案3】:

以下代码适用于您提供的所有场景

sed ':1;/^ *\/\*/{:2;/\*\/$/{d;b 1;};N;b 2;}' filename

【讨论】:

  • 由于您是新手并且最近正在写有趣的答案,请考虑使用{} 部分来正确格式化。此外,提供某种解释而不是仅仅“它有效”是一种很好的做法。
  • @fedorqui:当然。仍在努力理解何时使用什么以及最重要的是如何使用 :) 谢谢!
  • @Dipak 为什么您不认为我发布的 sed 解决方案不适用于所有场景?基本上你的 sed 命令看起来太复杂了。
  • @hek2mgl:您提供的解决方案不适用于“/* this "*/" is another comment dipak*/"之类的评论 :)
  • @Dipak 我在您上面发布的评论中对其进行了测试,它也将其删除了
猜你喜欢
  • 2011-05-11
  • 2011-01-28
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 2011-04-01
  • 2020-09-30
  • 1970-01-01
相关资源
最近更新 更多