【问题标题】:Using BASH - Find CSS block or definition and print to screen使用 BASH - 查找 CSS 块或定义并打印到屏幕
【发布时间】:2011-02-10 06:09:44
【问题描述】:

我有许多 .css 文件分布在一些目录中。我需要找到那些 .css 文件,阅读它们,如果它们包含特定的类定义,请将其打印到屏幕上。

例如,我正在寻找“.ExampleClass”,它存在于 /includes/css/MyStyle.css 中,我希望打印 shell 命令

.ExampleClass {
color: #ff0000;
}

【问题讨论】:

  • 你的问题是......?
  • @David:问题很明显是如何用单线来做到这一点。 @leonbloy:大概任何单行语言(awk、sed、perl)都可以。
  • 任何主要的动态语言(以及 shell)都可以完成这样的事情。
  • @Jefromi:这对你来说可能很清楚,但对我来说根本不清楚。
  • @David:是的,应该明确提出。但是有一行说“这里是示例输入和示例输出”和“shell命令”......

标签: regex bash unix terminal


【解决方案1】:

使用 find 过滤所有 css 文件,并在两个正则表达式之间对这些文件打印行执行 sed 脚本:

find ${DIR} -type f -name "*.css" -exec sed -n '/\.ExampleClass.{/,/}/p' \{\} \+

【讨论】:

  • 2 个问题:sed 是一个流编辑器,所以和我的解决方案一样,它不处理多行类。而-exec,虽然有效,但速度很慢。建议将 xargs 用于任何类型的繁重工作。
  • 使用了 exec+ 变体,因此实际命令行的构建方式与 xargs 构建其命令行的方式相同。 exec+ 不需要通过管道进行 IPC,因此它实际上比使用 xargs 更有效。
  • 大家的解决方法都很好看,大家可以借鉴。我刚刚抓住了这个,它正在为我的项目做我需要的事情。谢谢
  • 你是什么意思它不处理多行类?在我看来,它应该打印所有内容,包括匹配.ExampleClass.{} 的第一行之间的所有内容
【解决方案2】:

考虑到 css 文件可以有多行类定义,并且在同一个文件中可以有多次出现,我敢打赌 perl 是要走的路。

例如:

#input: css filename , and css class name without dot (in the example, ExampleClass)
my ($filen,$classn) = @ARGV;  
my $out = findclassuse($filen,$classn);
# print filename and result if non empty
print ("===== $filen : ==== \n" . $out . "\n") if ($out); 

sub findclassuse {
    my ($filename,$classname) = @_;
    my $output = "";
    open(my $fh, '<', $filename) or die $!;
    $/ = undef; # so that i read the full file content
    my $css  = <$fh>;
    $css =~ s#/\*.*?\*/# #g; # strip out comments
    close $fh;
    while($css =~ /([^}{]*\.$classname\b.*?{.*?})/gs) {
        $output .= "\n\n"  . $1;
    }
    return $output;
}

但这也不是100%万无一失,cmets还存在一些问题,而且css解析肯定不完美。

【讨论】:

    【解决方案3】:
    find /starting/directory -type f -name '*.css' | xargs -ti grep '\.ExampleClass' {}
    

    将找到所有的 css 文件,打印文件名和搜索字符串,然后打印 grep 的结果。您可以通过 sed 管道输出以删除任何不必要的文本。

    ETA:如果我们想捕捉多行表达式,正则表达式需要工作。很可能 EOL 字符应设置为 },以便将完整的类视为一行。如果这样做了,那么将find 传递给perl -e 而不是grep 会更有效

    【讨论】:

    • 这不会像问题中显示的 OP 那样找到多行块。它只会找到第一行。
    • 不应该是 grep '\.ExampleClass' 吗?
    • @Christopher W. Allen-Poole:已修复
    【解决方案4】:

    假设您从不做任何奇怪的事情,例如将左大括号放在单独的行上,或者在预期的右大括号之前放置一个未缩进(嵌套)的右大括号,您可以这样做:

    sed -n '/\.ExampleClass *{/,/^}/p' *.css
    

    如果文件都在一个目录结构中:

    find . -name *.css | xargs sed ...
    

    【讨论】:

    • 或者右大括号与类名和左大括号在同一行(见我的回答)。
    【解决方案5】:

    此版本处理多行块以及单行块:

    sed -n '/^[[:space:]]*\.ExampleClass[[:space:]]*{/{p;q}; /^[[:space:]]*\.ExampleClass[[:space:]]*{/,/}/p'
    

    例子:

    foo { bar }
    

    foo {
            bar
    }
    

    【讨论】:

    • +1;绝对比我的答案更强大,尽管对于一次性来说可能不太实用。 Wheeeeeeeeeee,sed。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    相关资源
    最近更新 更多