1. 程式人生 > >jQuery選擇器探究:正則表示式彙總

jQuery選擇器探究:正則表示式彙總

jQuery選擇器正則表示式是jQuery選擇器框架Sizzle的基礎。Sizzle正則表示式集中在Expr物件的match物件屬性中,這裡定義的RE是基礎的、按照功能分類的。另一個核心RE是變數chunker定義的。

一 Expr物件的正則表示式

	match: {
		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
	}

分析這些RE的思路:一是按順序找出所有的分組(程式解析過程與分組緊密相關),二是清晰其結構。分組用顏色表示(這裡用了兩種顏色以區分位置上連續的但邏輯上不連續的分組),結構區分用換行。







這樣定義的Sizzle的所有正則表示式從功能上來講差不多是夠了,但是從健壯性的角度來講還遠遠不夠,畢竟一套健壯的機器不能僅僅期望使用者嚴格按照操作說明文件來輸入或操作,在使用者非常規的甚至錯誤的輸入資料或操作時依然能正確運轉的才是成熟的產品,為此Sizzle對match正則物件做了統一處理並給出了一套增強版的leftMatch物件。

var origPOS = Expr.match.POS,
	fescape = function(all, num){
		return "\\" + (num - 0 + 1);
	};

for ( var type in Expr.match ) {
	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
}

對match的統一處理邏輯是:在正則表示式前面(右方)追加一個驗證當前正則表示式正確性的反前向錨,即當前正則表示式的前方不能出現一個未經匹配的孤立的右方括號或者右圓括號。
在此基礎上,在正則表示式後面(左方)追加一個同樣是驗證作用的捕獲分組,這時問題來了,在正則表示式前面(右方)追加錨時不涉及到分組,不會對已存在的正則表示式物件產生影響(即使追加的是分組也不會影響已存在的正則表示式),但是在正則表示式後面(左方)追加分組時會影響已存在的正則表示式物件--原分組數字後向引用如果不依次遞增將會引用錯誤的分組,此時不得不修正改動已存在的正則表示式物件(主要是分組引用數字值增一),這就是fescape函式在replace方法中的作用。經過前後增強的正則表示式物件存入Expr的leftMatch物件中,後面我們會看到,Sizzle實際使用的是增強的match物件和leftMatch物件。

二 chunker變數

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g