web-dev-qa-db-ja.com

CSS 16進数の色を一致させるための正規表現

CSSコードからすべての16進数の色を抽出する正規表現を記述しようとしています。

これは私が今持っているものです:

コード:

$css = <<<CSS

/* Do not match me: #abcdefgh; I am longer than needed. */

.foo
{
    color: #cccaaa; background-color:#ababab;
}

#bar
{
    background-color:#123456
}
CSS;

preg_match_all('/#(?:[0-9a-fA-F]{6})/', $css, $matches);

出力:

Array
(
    [0] => Array
        (
            [0] => #abcdef
            [1] => #cccaaa
            [2] => #ababab
            [3] => #123456
        )

)

句読点、空白、改行で終わる色だけが一致するように指定する方法がわかりません。

32
Hemaulo

16進数のカラーコードも3文字で構成される場合があるため、必須のグループとオプションの文字と数字のグループを定義できるため、長くて複雑な表記は次のようになります。

/#([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?\b/

または、ナイスショートバージョンが必要な場合は、3つの英数字からなる1つまたは2つのグループが必要であり、大文字と小文字を区別せずに一致させる必要がある(/i)。

/#([a-f0-9]{3}){1,2}\b/i

の代わりに [a-f0-9]次のように書くこともできます[[:xdigit:]]、正規表現エンジンがこのposix文字クラスをサポートする場合。この場合、/i最後に、式全体はあと2文字だけですが、間違いなく説明的です。

/#([[:xdigit:]]{3}){1,2}\b
48
GolezTrol

GolezTrolの回答 の短縮バージョンは、文字セットを2回書き込むことを回避します。

/#([a-fA-F0-9]{3}){1,2}\b/
21
robinst

受け入れられた答えは、それがあなたの質問だったので、正規表現でそれを行う方法を示しています。しかし、これには正規表現を使用する必要はありません。通常、これは私がそれを行う方法です:

if(ctype_xdigit($color) && strlen($color)==6){
    // yay, it's a hex color!
}

100.000反復の場合:

正規表現ソリューション*:0.0802619457245秒

Strlen付きのXdigit:0.0277080535889秒

*:16進数:([a-fA-F0-9]{6})

18
modu

この質問の年齢にもかかわらず、私は以下を賞賛したいと思います:

^#([[:xdigit:]]{3}){1,2}$、ここで_[[:xdigit:]]_は_[a-fA-F0-9]_の省略形です。

そう:
<?php preg_match_all("/^#(?>[[:xdigit:]]{3}){1,2}$/", $css, $matches) ?>

また、注目に値するのは、キャプチャしないグループ_(?>...)_の使用です。これは、最初に保存したくないメモリにデータを保存しないようにするためです。

オンラインでお試しください

2
Berry M.

これが正しいかどうかは完全にはわかりませんが、CSS行の最後の16進数の色だけを一致させたい場合は、次のようにします。

preg_match_all('/#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})[\s;]*\n/',$css,$matches);

動作するはずですが、私がしたことはオプションの\s;文字グループ(オプションのセミコロンとスペース)と改行文字(オプションではない)が機能しているようです。
そして@GolezTrolが指摘したように#FFF;も有効です。

これでテストすると:

$css = '/* Do not match me: #abcdefgh; I am longer than needed. */
.foo
{
    color: #CAB;
    background-color:#ababab;
}';
preg_match_all('/#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})[\s;]*\n/',$css,$matches);
var_dump($matches);

出力は次のとおりです。

array (array('#CAB;','#ababab;'))
0