2009-06-04 19 views
1

長年のユーザーからの最初の質問。PerlでCSSを検索するにはどうすればよいですか?

私はいくつかのHTMLファイルを調べ、「color:」や「background-color:」(CSSタグ)のインスタンスを一行ずつ検索し、これらのインスタンスのいずれかを参照すると、行全体が表示されます。これはかなり簡単です。

私はまだ初心者ですが、この次の部分は非常に明白かもしれませんが、私はここに来ました。

"color:"または "background-color:"のインスタンスが見つかったときに、それをトレースして要素の名前を探して印刷したいと思っています。私の文書は、以下のCSS含まれる場合

:たとえば

css_class,#FFEFA1 

理想的には、それがテキストファイルとして出力し、これを希望:

.css_class { 
    font-size: 18px; 
    font-weight: bold; 
    color: #FFEFA1; 
     font-family: Arial, Helvetica, sans-serif; 
} 

を私のような何かを出力するスクリプトをしたいでしょう。

私はこのことについて私に与えられたアドバイスを大変感謝しています!ここで

はこれまで、フルで私のスクリプトです:

$color = "color:"; 


open (FILE, "index.html"); 
@document = `<FILE>`; 
close (FILE); 

foreach $line (@document){ 
    if($line =~ /$color/){ 
     print $line; 
    } 
} 

答えて

5

アドバイスを求められたので(これはコーディングサービスではありません)、私はをちょうどとします。

open(FILE, 'filename') or die "Can't read file 'filename' [$!]\n"; 

利用代わりグロブのオープンと字句ファイルハンドルの三引数の形式::

use strict; 
use warnings; 

は必ずopen呼び出しの戻り値をチェックします。

必ず狭窄と警告を使用します

open(my $fh, '<', 'filename') or die "Can't read file 'filename' [$!]\n"; 

行単位で処理するときにスラップしないでください。

while (my $line = <$fh>) { 
    # do something with $line 
} 

使用後方参照は正規表現のマッチからデータを取得します

if ($line =~ /color *: *(#[0-9a-fA-F]{6})/) { 
    # color value is in $1 
} 

保存一時変数で、クラス名、あなたがそれを持っていることをあなたは色と一致して:まあ

if ($line =~ /^.(\w+) *\{/) { 
    $class = $1; 
} 
+0

私はまだこれが必要な答えではないと思います。優れた一般的なアドバイス、思考。 –

+0

はい、このアドバイスは非常に役に立ちました。ありがとう。私は過去数時間のうちに、私が解決策に近づいている様子をもう少し見てきました。私は正規表現の問題ではなく、むしろデータのキャプチャを持っています。 CSS要素は通常複数行であるため、リスト項目の区切り文字として{と}の間に配列を作成する方法を理解する必要があります。このデータが必要な最終的な(改訂された)番号は次のとおりです(例) 本文:#000000 – goddamnyouryan

+1

すべてのCSS要素が複数行であるわけではありません。多くの単純なケースでは、1行に複数のプロパティが宣言されています。たとえば、次のようになります。* {margin:0;パディング:0; } – Telemachus

-1

私は以下のコードをテストしていませんが、このような何かが動作するはずですが:

if ($line =~ m/\.(.*?) \{(.*?)color:(.*?);(.*)/) { 
print "$1,$3\n"; 
} 

あなたが定期的に学習いくつかの時間を投資する必要がありますPerlの式。

+0

することはできませんこれは本当に悪い正規表現です。 1つは、スペースの代わりに\ sを使用します。/ iと/ mのような正規表現修飾子を使用していません。最後に、色のプロパティがない場合はどうなりますか? –

2

を、これはそう簡単ではありません。

CSSクラスはさまざまな方法で定義できます。たとえば、

.classy { 
     color: black; 
    } 

これを解析するための行単位のアプローチを使用してください。

実際、私の最初のアプローチはCPANの検索です。これは有望に見える:

CSS - Object oriented access to Cascading Style Sheets (CSS)

編集:私はCPANからHTML :: TreeBuilderとCSSモジュールをインストールし、次収差でっち上げ

:すべて

use strict; 
use HTML::TreeBuilder; 
use CSS; 

foreach my $file_name (@ARGV) { 
    my $tree = HTML::TreeBuilder->new; # empty tree 
    $tree->parse_file($file_name); 

    my $styles = $tree->find('style'); 

    if ($styles) { 
     foreach my $style ($styles) { 
      # This is an insane hack, not guarantee 
      # to work in the future. 
      my $css = CSS->new; 
      $css->read_string(join "\n", @{$style->{_content}}); 

      print $css->output; 
     } 
    } 
    $tree = $tree->delete; 
} 

この事だけプリントをCSSセレクタはHTMLファイルのリストから作成されますが、ここから続けることができるように整形されています。

+1

行ごとに解析するのは難しいことではありません。クラス名を見つけたらクラス名のコピーを保存するだけです。 CPANを使うのは良いことですが、これはPerlの初心者が自分の歯を切るための良い(簡単な)練習です。 –

+0

マイケル、あなたがCSSを解析することの困難を見ることができない場合は、あなたはそれを考えていないと思う。 CSSを解析するには、再帰的降下パーサを実装する必要があります。 –

+0

私はあなたの例に取り組んでいました。一般的なケースではありません。 –

2

さらに別の方法として、perlに、行以外のファイルの読み込みを要求することができます。たとえば、レコード区切り文字として "}"を使用します。

my $color = "color:"; 

open (my $fh, '<', "index.html") || die "Can't open file: $!"; 

{ 
    local $/ = "}"; 
    while(my $section = <$fh>) { 
    if($section =~ /$color(.*)/) { 
     my ($selector) = $line =~ /(.*){/; 
     print "$selector, $section\n"; 
    } 
} 

未テスト!また、これは当然ながら、あなたのCSSがセクションをaで終わらせていることを前提としています。

+0

slick!箱の外で考える方法。 –

1

私は正規表現に問題はありませんが、データのキャプチャではありません。 CSS要素は通常複数行であるため、リスト項目の区切り文字として{と}の間に配列を作成する方法を理解する必要があります。

いいえ、ありません。

述べたような問題のために、関心ののみ線はクラス名または色の定義のいずれかを含有するもの、およびクラスの終わりをマークするために}を含む可能性もラインであろう。他の行はすべて無視することができるので、配列に入れる必要はありません。

クラス仕様はネストすることができないため、最後に見たクラス名のセットは常にアクティブなクラスセットになります。したがって、最後に表示されたクラス名のセットだけを記録すればよく、カラー指定があった場合は、それらのクラス名を印刷します。

仕様ブロックが複数のクラス(.foo, .bar, .baz { ... })で共有されているケースを処理する可能性がありますが、複数の行にまたがっている場合とそうでない場合があります。複数の属性が同じ行に定義されていても、それらは既に私が既に計画したものからかなり簡単に続くべきです。入力データに応じて、コメントの有無を追跡するために、基本的な状態エンジンを組み込む必要があるかもしれません。

[1]つまり、あなたがそのような.foo.foo .barとして意味的に、ネストされたクラスを持つことができますが、彼らは

.foo { 
    ... 
} 
.foo .bar { 
    ... 
} 

としてCSSファイルで指定する必要があり、

.foo { 
    ... 
    .bar { 
    ... 
    } 
} 
関連する問題