ฮ่าๆ เรามาเริ่มกันที่คำไม่กี่คำกันดีกว่า ปีที่แล้วฉันใช้ C# เพื่อสร้างเครื่องมือเน้นไวยากรณ์ มันจัดรูปแบบโค้ดที่กำหนดเป็น HTML ตามข้อมูลในไฟล์กำหนดค่า เพื่อให้สามารถแสดงไวยากรณ์เดียวกันบนหน้าเว็บได้ ในตัวแก้ไขเอฟเฟกต์การเน้นองค์ประกอบและการรองรับการพับโค้ด ถูกต้องมันคล้ายกับสิ่งที่คุณเห็นในบล็อก เนื่องจากตอนนั้นฉันใช้ MSN Space จึงไม่มีฟังก์ชันนี้ ฉันจึงต้องเขียนเอง
ฉันใช้ C# ในการเขียน ตอนแรกฉันใช้คำสั่งพื้นฐานที่ยุ่งยากมาก เช่น for, while, switch, if ฯลฯ เพื่อตัดสินคีย์เวิร์ด ฯลฯ อย่าหัวเราะเยาะฉันเลย ฉันโง่และไม่รู้ว่าอะไร นิพจน์ทั่วไปในเวลานั้นดังนั้นฉันจึงใช้วิธีหยาบนี้ได้เท่านั้น แน่นอนว่าวิธีแบบหยาบยังคงใช้ได้ผลอยู่ มันเป็นเพียงโค้ดยาวในฟังก์ชัน ในอนาคตฉันคิดว่าจะเป็นเรื่องยากมาก ซอฟต์แวร์อื่นไม่สามารถเขียนแบบนี้ได้ ดังนั้น... หลังจากค้นหาใน Google มาระยะหนึ่งแล้ว ฉันพบโค้ดและโครงการโอเพ่นซอร์สที่มีการเน้นไวยากรณ์ และเริ่มดู - - - - ว้าว ทุกอย่างซับซ้อนมาก พูดตามตรง สิ่งที่ฉันไม่ชอบทำมากที่สุดคือการดูโค้ดของคนอื่น ฉันไม่ได้เสแสร้ง แต่การดูโค้ดของคนอื่นมันน่าสับสนจริงๆ คำอธิบายเอกสารที่มีรายละเอียดมาก ไม่เช่นนั้นฉันจะไม่อยากดูมันตั้งแต่แรกเห็น อย่างมาก ฉันแค่ดูว่าคนอื่นเขียนอินเทอร์เฟซอย่างไร แล้วเดาว่ามันถูกนำไปใช้ภายในอย่างไร
แม้ว่าการค้นหาจะไม่เป็นประโยชน์มากนัก แต่ก็ยังทำให้ฉันรู้เกี่ยวกับสำนวนปกติ ฉันลืมไปแล้วว่าฉันเห็นมันที่ไหน ในเวลานั้น ฉันเริ่มศึกษาสำนวนปกติไปพร้อมกับปรับปรุง "สิ่งที่เสียหาย" ของฉันไปด้วย ไม่นานหลังจากนั้น ฉันเริ่มเขียนบล็อกอีกครั้งใน Blog Park และในที่สุดก็เปิดใช้งานฟังก์ชันเน้นไวยากรณ์ของ Blog Park ดังนั้นฉันจึงสูญเสียแรงจูงใจหลักในการเขียนโค้ดของตัวเองเพื่อเน้น HTML ประการที่สอง โมดูลเน้นไวยากรณ์ที่สร้างใน C# สามารถทำงานได้บนฝั่งเซิร์ฟเวอร์หรือโปรแกรม WinForm เท่านั้น และสิ่งที่ฉันต้องการได้รับในท้ายที่สุดคือโค้ด HTML ที่จะแสดงบนเพจ ฉันคิดว่าสคริปต์ฝั่งไคลเอ็นต์เหมาะสมที่สุดสำหรับงานนี้ น่าเสียดายที่ฉันไม่ค่อยรู้เรื่อง JS มากนัก - - ต่อมา ฉันเริ่มยุ่งกับสิ่งอื่นๆ ในช่วงเวลานี้ และไม่ได้ปรับปรุงโมดูลเน้นไวยากรณ์
เมื่อคืนฉันทำงานล่วงเวลาและกลับมาถึงบ้าน เดิมทีฉันวางแผนที่จะเรียนรู้ UML ต่อไปและดูรูปแบบ จากนั้นฉันก็จำได้ว่าบริษัทมีโมดูลที่จำเป็นต้องลบแท็ก HTML ทั้งหมดในผลลัพธ์ที่ส่งคืนโดยฐานข้อมูล ดังนั้นฉันจึงเปิดโมดูลปกติ เครื่องมือนิพจน์ RegexBuddy ด้วยเหตุนี้ ฉันเห็นบทช่วยสอนง่ายๆ เกี่ยวกับการใช้นิพจน์ทั่วไปใน JScript ในเอกสารช่วยเหลือของ RegexBuddy ดังนั้นฉันจึงเกิดความอยากรู้อยากเห็นอีกครั้ง ดังนั้นฉันจึงเปิด UltraEdit-32 และเริ่มเขียน JavaScript อย่างง่ายเพื่อทดลอง
ฉันจะไม่ลงรายละเอียดเกี่ยวกับกระบวนการทดสอบของฉันที่นี่ เนื่องจากหลายแห่งเกี่ยวข้องกับการทดสอบซ้ำๆ และการเปลี่ยนเส้นทางหลายครั้ง ในที่นี้ ฉันจะให้การใช้นิพจน์ทั่วไปใน JScript ที่ฉันสรุปจากการทดสอบโดยตรง
หมดเรื่องไร้สาระแล้ว เรามาเข้าประเด็นกันดีกว่า!
นายกรัฐมนตรีพูดถึง RegExp วัตถุนิพจน์ทั่วไปของ JScript
ชื่อคลาสที่ให้การดำเนินการนิพจน์ทั่วไปใน JScript คือ RegExp และออบเจ็กต์ประเภท RegExp สามารถสร้างอินสแตนซ์ได้สองวิธี
วิธีที่ 1 การสร้างอินสแตนซ์คอนสตรัคเตอร์:
var myRegex = new RegExp(" \w +", "igm ");
//w+ คือนิพจน์ทั่วไปที่แท้จริง โปรดทราบว่า ตัวแรกมีไว้สำหรับการหลบหนี igm หมายถึงการละเว้นตัวพิมพ์เล็กและใหญ่ การค้นหาทั่วโลก และการค้นหาหลายบรรทัดตามลำดับ ซึ่งจะอธิบายในภายหลัง
วิธีที่สอง วิธีการกำหนดโดยตรง:
var myRegex = /w+/igm;
//เอฟเฟกต์จะเหมือนกับคำสั่งก่อนหน้า ยกเว้นว่าไม่จำเป็นต้องใช้อักขระถ่ายโอนที่นี่ นิพจน์ทั่วไปดั้งเดิมจะมีลักษณะเหมือนกับ igm ในตัวอย่างก่อนหน้า
วิธีการเฉพาะที่ใช้นั้นขึ้นอยู่กับความชอบของทุกคน โดยส่วนตัวแล้ว ฉันคิดว่าวิธีที่สองจะอ่านง่ายกว่าเมื่อเขียน regex วัตถุ RegExp มีการดำเนินการดังต่อไปนี้:
exec(string str): ดำเนินการจับคู่นิพจน์ทั่วไปและส่งกลับผลลัพธ์ที่ตรงกัน ตามตัวอย่างผลลัพธ์ที่รันโดย MSDN การดำเนินการแต่ละครั้งของ exec จะเริ่มต้นจากจุดสิ้นสุดของการจับคู่โดยตรงครั้งล่าสุด ดูเหมือนว่าค่าที่ส่งคืนจะเป็นวัตถุ RerExp และคำอธิบายที่กำหนดโดย RegexBuddy คือการส่งคืนอาร์เรย์ แต่ไม่มีตัวอย่างโดยละเอียด ฉันคิดว่ามันน่าเชื่อถือมากขึ้นตามผลการทดลอง
คอมไพล์ (regex สตริง แฟล็กสตริง): คอมไพล์นิพจน์ทั่วไปล่วงหน้าเพื่อให้ทำงานเร็วขึ้น หลังจากการทดสอบ ประสิทธิภาพจะดีขึ้นอย่างมากหลังจากการคอมไพล์ล่วงหน้า พารามิเตอร์ regex เป็นนิพจน์ทั่วไป และแฟล็กสามารถเป็นการรวมกันของค่าสามค่าต่อไปนี้: g – การค้นหาทั่วโลก ผลการทดสอบของฉันคือว่าหากไม่มีการเพิ่มแฟล็ก g จะสามารถจับคู่ได้เฉพาะสตริงที่ผ่านการรับรองตัวแรกเท่านั้น โดยไม่สนใจตัวพิมพ์เล็กและใหญ่ – การค้นหาหลายบรรทัดดูเหมือนจะเป็นการค้นหาหลายบรรทัดโดยค่าเริ่มต้น
การทดสอบ (สตริง str): หาก str ตรงกับนิพจน์ทั่วไป ก็จะส่งกลับค่าจริง มิฉะนั้นจะส่งกลับค่าเท็จ วิธีจับคู่นี้คล้ายกับวัตถุสตริงวัตถุ
RegExp มีคุณลักษณะต่อไปนี้ :
ดัชนี: ในสตริง ตำแหน่งของนิพจน์ที่ตรงกันแรก เริ่มต้น -1
อินพุต: เป้าหมายที่ตรงกันของนิพจน์ทั่วไป โปรดทราบว่าเป็นแบบอ่านอย่างเดียว
LastIndex: ตำแหน่งของนิพจน์ที่ตรงกันถัดไป คือ (ส่งคืนตำแหน่งอักขระที่การจับคู่ถัดไปเริ่มต้นในสตริงที่ค้นหา) ฉันไม่รู้ว่ามีข้อผิดพลาดในการแปลหรือไม่ ฉันไม่ได้ใช้แอตทริบิวต์นี้
LastMatch: สตริงสุดท้ายที่ตรงกับนิพจน์
LastParen: สตริงการจับคู่ย่อยที่ตรงกันล่าสุด ตัวอย่างเช่น หากมีการจับคู่หลายรายการที่จัดกลุ่มตาม () ในนิพจน์ทั่วไป LastParen จะแสดงถึงกลุ่มสุดท้ายของผลลัพธ์ที่ตรงกัน
leftContext: อักขระทั้งหมดตั้งแต่จุดเริ่มต้นของสตริงเป้าหมายจนถึงตำแหน่งเริ่มต้นของนัดสุดท้าย
rightContext: อักขระทั้งหมดตั้งแต่ท้ายรายการสุดท้ายจนถึงจุดสิ้นสุดของสตริงเป้าหมายทั้งหมด
$1...$9: ระบุผลลัพธ์ของกลุ่มที่ n ของการจับคู่ สิ่งนี้มีประโยชน์เมื่อมีหลายกลุ่ม () ในนิพจน์ทั่วไป
ต่อไป เรามาพูดถึงการดำเนินการที่เกี่ยวข้องกับวัตถุ String และนิพจน์ทั่วไปใน JScript:
match (regex สตริง): ยอมรับนิพจน์ทั่วไปและส่งกลับว่าสตริงตรงกับนิพจน์หรือไม่
แทนที่ (srting regex, string str): แทนที่สตริงย่อยที่ตรงกับนิพจน์ทั่วไปด้วย str ฟังก์ชันนี้ดูเหมือนง่าย แต่ยังซ่อนการใช้งานขั้นสูงเพิ่มเติมด้วย โปรดดูตัวอย่างต่อไปนี้
ตัวอย่างที่ 1:
var str1 = "A:ฉันชื่อปีเตอร์!nB:สวัสดีปีเตอร์!";
str1 = str1.replace(/Peter/g,"แจ็ค");
การแจ้งเตือน (str1);
ตัวอย่างนี้ทำได้ง่ายเพียงแค่แทนที่สตริง แน่นอนว่า พลังของนิพจน์นี้ไม่ได้จำกัดอยู่เพียงเท่านี้ หากคุณเชี่ยวชาญการใช้มัน คุณยังสามารถใช้มันเพื่อทำงานหลายอย่างที่ก่อนหน้านี้ต้องใช้โค้ดจำนวนมากได้ ตัวอย่างเช่น เพิ่มแท็ก HTML ที่ไฮไลต์ก่อนและหลังคีย์เวิร์ดโค้ด จากตัวอย่างก่อนหน้านี้ ดูเหมือนว่าการแทนที่สามารถแทนที่ข้อความที่ตรงกันด้วยข้อความใหม่เท่านั้น ฉันจะใช้มันเพื่อแทรกแท็กก่อนและหลังคีย์เวิร์ดได้อย่างไร ลองนึกย้อนกลับไปว่าถ้าคุณสามารถใช้ผลลัพธ์ที่ตรงกันเมื่อแทนที่ สิ่งต่างๆ จะง่ายขึ้น เพียงแทนที่คำหลักด้วย: tag header + keyword + tag tail
แต่จะใช้ผลลัพธ์ของการจับคู่นิพจน์ทั่วไปในการแทนที่ได้อย่างไร
ในเวลานี้เราจำเป็นต้องใช้ "ตัวแปรที่ตรงกัน" เพื่อแสดงผลลัพธ์ของการจับคู่ปกติ ต่อไปนี้เป็นคำอธิบายของตัวแปรที่ตรงกัน:
$& -- แสดงถึงผลลัพธ์ที่ตรงกันของกลุ่มที่ตรงกันทั้งหมด สุดท้าย กลุ่มที่ตรงกันคือกลุ่ม () ของนิพจน์ทั่วไป
$$ -- แทนอักขระ $ เนื่องจากตัวแปรที่ตรงกันใช้อักขระ $ จึงจำเป็นต้องหลีกเลี่ยง
$n -- คล้ายกับ $1...$9 ก่อนหน้า ซึ่งระบุผลลัพธ์ที่ตรงกันชุดที่ n
$nn -- ง่ายมาก ๆ เป็นผลจากการแข่งขันกลุ่มที่ n
$` -- คือ leftContext ที่กล่าวถึงก่อนหน้านี้ ตัวอย่างเช่น หาก abcdefg จับคู่กับ d ดังนั้น abc จะเป็น leftContext
$' -- ใกล้เคียงกับข้อความข้างต้นมาก อย่าอ่านผิด! นี่คือ rightContext โดยการเปรียบเทียบ efg คือ rightContext ของตัวอย่างข้างต้น ดังนั้น ตอนนี้จึงเป็นเรื่องง่ายมากสำหรับเราที่จะแทรกแท็กก่อนและหลังคำหลัก:
var str1 = "A:ชื่อของฉันคือ Peter!nB:สวัสดี ปีเตอร์!" ;
str1 = str1.replace(/ปีเตอร์/g, "<b>$&</b>");
การแจ้งเตือน (str1);
00:39น.แล้ว - - เรามาหยุดที่นี่กันเถอะ
ดาวน์โหลดซอฟต์แวร์เครื่องมือปกติ (รหัสผ่าน: regex): regex Buddy 2.06.zip
โปรดดูตัวอย่างที่ฉันเขียน: การเน้นไวยากรณ์ JScript (การปรับปรุงโค้ด)
นี่คือตัวอย่างบางส่วนจาก MSDN:
function matchDemo()
-
วาร์ส;
var re = new RegExp("d(b+)(d)", "ig");
var str = "cdbBdbsbdbdz";
var arr = re.exec(str);
s = "$1 ประกอบด้วย: " + RegExp.$1 + "n";
s += "$2 ประกอบด้วย: " + RegExp.$2 + "n";
s += "$3 มี:" + RegExp.$3;
ส่งคืน;
-
ฟังก์ชั่น RegExpTest()
-
var ver = Number(ScriptEngineMajorVersion() + "." + ScriptEngineMinorVersion())
ถ้า (เวอร์ชั่น >= 5.5){
var src = "ฝนตกในสเปนส่วนใหญ่อยู่ในที่ราบ";
var ใหม่ = /w+/g;
วาร์ arr;
ในขณะที่ ((arr = re.exec(src)) != null)
พิมพ์ (arr.index + "-" + arr.lastIndex + "t" + arr);
-
อื่น{
alert("คุณต้องมี JScript เวอร์ชั่นใหม่กว่าจึงจะใช้งานได้");
-
}
ฟังก์ชัน matchDemo()
-
var s; //ประกาศตัวแปร
var re = new RegExp("d(b+)(d)", "ig"); // รูปแบบนิพจน์ทั่วไป
var str = "cdbBdbsbdbdz"; //สตริงที่ต้องการค้นหา
var arr = re.exec(str); //ทำการค้นหา
s = "$1 ส่งคืน: " + RegExp.$1 + "n";
s += "$2 ส่งคืน: " + RegExp.$2 + "n";
s += "$3 ส่งคืน: " + RegExp.$3 + "n";
s += "อินพุตส่งคืน : " + RegExp.input + "n";
s += "lastMatch ส่งคืน: " + RegExp.lastMatch + "n";
s += "leftContext ส่งคืน: " + RegExp.leftContext + "n";
s += "rightContext ส่งคืน: " + RegExp.rightContext + "n";
s += "lastParen ส่งคืน: " + RegExp.lastParen + "n";
ส่งคืน // ส่งคืนผลลัพธ์
-
document.write(matchDemo());
หากฮีโร่คนไหนที่ผ่านไปมามีความคิดเห็นเกี่ยวกับบทความนี้ โปรดอย่าลังเลที่จะโพสต์ไว้ที่นี่ มาเรียนรู้และก้าวหน้าไปด้วยกัน