原文:http://regexadvice.com/blogs/mash/archive/2008/03/27/Additional-CSS-minifying-regex-patterns.aspx
注意:本文提到的Regex都使用了IgnoreCase=true選項。
我觀察了YUI Compressor中用於精簡CSS的Regex,並給出了一些我認為能有助於這一工作的其他Regex。
我所看到的代碼已經能夠通過簡單的字串替換修剪掉“上-右-下-左”值中不必要的零值。但這是通過三個獨立的替換操作完成的。如果能用Regex處理這種情況,代碼將會變得更簡單。
(虛擬碼)
string.Replace(":0 0 0 0;","0;")
string.Replace(":0 0 0;","0;")
string.Replace(":0 0;","0;")
可以變為:
Regex.Replace(input,":("s*0)("s+0){0,3}"s*;",":0;")
夠簡單了吧。但我想,怎麼能就此停滯不前呢?於是我給出了可以處理所有數值的Regex:
:"s*(0|(?:(?:"d*".?"d+(?:p(?:[xct])|(?:[cem])m|%|in|ex))))("s+"1){1,3};
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=d090db4eaf3b41e2b4e75290ad5fe670)
用於進行替換的字串很簡單:“:$1”。
這一步完成後,下面就是處理各個數值並不全為0的情形。
如果您不大瞭解CSS,這裡簡單說一下,此處可能出現4個值:
1)如果只指定一個值,則另外三個值也都隱式地指定為相同的值(X = X X X);
2)如果指定了二個值,則第三個值和第一個相等,第四個值和第二個相等(X Y = X Y X Y);
3)如果指定了三個值,則第四個值等於第二個值(X Y Z = X Y Z Y)。
當然,在精簡時您肯定希望用更短的文法。下面的Regex可以使其變短。所有這些情況使用的替換字串都和前面一樣,是“:$1”。
將4個參數替換為2個(X Y X Y變為X Y)
:"s*((0|(?:(?:"d?".?"d(?:p(?:[xct])|(?:[cem])m|%|in|ex))))"s+(0|(?:(?:"d?".?"d(?:p(?:[xct])|(?:[cem])m|%|in|ex)))))"s+"2"s+"3;
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=e47bbb7741bd438e9fd37cae7a9d4a24)
4個變為3個(X Y Z Y變為X Y Z)或3個變為2個(X Y X變為X Y)
:"s*((?:(?:0|(?:(?:"d?".?"d(?:p(?:[xct])|(?:[cem])m|%|in|ex))))"s+)?(0|(?:(?:"d?".?"d(?:p(?:[xct])|(?:[cem])m|%|in|ex))))"s+(?:0|(?:(?:"d?".?"d(?:p(?:[xct])|(?:[cem])m|%|in|ex)))))"s+"2;
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=6bddaab88e724f68a5808d352cc556ca)
較長的這個Regex只不過是重複了其中一個子模式而已。
基於以上這些Regex,我提出了類似的模式,用來處理border-style、outline-style、border-color和outline-color。
border-style/outline-style
替換字串為“$1-style:$2;”。
(outline|border)-style"s*:"s*(none|hidden|d(?:otted|ashed|ouble)|solid|groove|ridge|inset|outset )(?:"s+"2){1,3};
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=e46542e4f8bb48429a9f5c9b7fdc546b)
(outline|border)-style"s*:"s*((none|hidden|d(?:otted|ashed|ouble)|solid|groove|ridge|inset|outset )"s+(none|hidden|d(?:otted|ashed|ouble)|solid|groove|ridge|inset|outset ))(?:"s+"3)(?:"s+"4);
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=c5e39786b75143588049042aea0dcd41)
(outline|border)-style"s*:"s*((?:(?:none|hidden|d(?:otted|ashed|ouble)|solid|groove|ridge|inset|outset )"s+)?(none|hidden|d(?:otted|ashed|ouble)|solid|groove|ridge|inset|outset )"s+(?:none|hidden|d(?:otted|ashed|ouble)|solid|groove|ridge|inset|outset ))(?:"s+"3);
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=6558eb133f26435cba770aa1c69f91dd)
border-color/outline-color
替換字串為“$1-color:$2;”。
(outline|border)-color"s*:"s*((?:"#(?:[0-9A-F]{3}){1,2})|"S+)(?:"s+"2){1,3};
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=05ec5037fcf843609e14c821b7f76034)
(outline|border)-color"s*:"s*(((?:"#(?:[0-9A-F]{3}){1,2})|"S+)"s+((?:"#(?:[0-9A-F]{3}){1,2})|"S+))(?:"s+"3)(?:"s+"4);
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=4a4c4e9dcdf74a97ba3daa113e56a9ca)
(outline|border)-color"s*:"s*((?:(?:(?:"#(?:[0-9A-F]{3}){1,2})|"S+)"s+)?((?:"#(?:[0-9A-F]{3}){1,2})|"S+)"s+(?:(?:"#(?:[0-9A-F]{3}){1,2})|"S+))(?:"s+"3);
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=82fedb7249b041f3a13e5552fc626b47)
我還給出了其他一些用於替換代碼的Regex,但由於它們都使用了反相匹配,所以移植性會有問題。
這個模式:
"s+((?:[!{};>+()"],])|(?<={[^{}]*):(?=[^}]*}))
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=928254009ef849cfb565022b6489355e)
用於匹配字元前面不必要的空白字元。要小心偽選取器和偽類前面的冒號。替換字串為“$1”。
這個模式:
(?<!["x22"x27=]"s*)"#([0-9A-F])"1([0-9A-F])"2([0-9A-F])"3
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=1e210252d62d4cd2a9f0cb9f2513aeb8)
用於精簡16進位顏色值,將AABBCC變為ABC。替換字串為“$1$2$3”。
我還寫了一個用於匹配形如“rgb(x,y,z)”的RGB值的Regex,其中的x、y、z都在0-255之間。
rgb"s*"x28((?:25[0-5])|(?:2[0-4]"d)|(?:[01]?"d?"d))"s*,"s*((?:25[0-5])|(?:2[0-4]"d)|(?:[01]?"d?"d))"s*,"s*((?:25[0-5])|(?:2[0-4]"d)|(?:[01]?"d?"d))"s*"x29
(【譯註】測試地址:http://regex-lib.net/Regex/Test/?id=c616455c751647ff9c1a430f4f0cfb96)
這個模式僅用於匹配現有代碼,並將每個數值放到一個組中,以便進行進一步處理。可以使用matchevaluator遍曆每一個匹配並完成10進位到16進位的轉換。
我自己進行了一些alpha測試,但我寫的css根本不能用作測試材料,所以乾脆給大家進行beta測試。我並不是很懂CSS hack,因此我不知道這些精簡會不會對CSS hack產生負面影響。我還會將這些資訊告訴YUI Compressor的維護者,看看他們能不能採納。