ฉันไม่เข้าใจนิพจน์ทั่วไปจริงๆ คุณช่วยอธิบายพวกเขาให้ฉันฟังได้ง่ายๆ หากมีเครื่องมือหรือหนังสือออนไลน์คุณสามารถลิงก์ไปยังพวกเขาได้หรือไม่?
ฉันไม่เข้าใจนิพจน์ทั่วไปจริงๆ คุณช่วยอธิบายพวกเขาให้ฉันฟังได้ง่ายๆ หากมีเครื่องมือหรือหนังสือออนไลน์คุณสามารถลิงก์ไปยังพวกเขาได้หรือไม่?
คำตอบ:
ส่วนที่สำคัญที่สุดคือแนวคิด เมื่อคุณเข้าใจการทำงานของ Building Block แล้วความแตกต่างของจำนวนไวยากรณ์จะมากกว่าภาษาถิ่นเล็กน้อย เลเยอร์ด้านบนของไวยากรณ์เอ็นจินนิพจน์ปกติของคุณคือไวยากรณ์ของภาษาการเขียนโปรแกรมที่คุณใช้ ภาษาเช่น Perl ลบภาวะแทรกซ้อนนี้ส่วนใหญ่ แต่คุณจะต้องคำนึงถึงข้อควรพิจารณาอื่น ๆ หากคุณใช้นิพจน์ปกติในโปรแกรม C
หากคุณคิดว่านิพจน์ทั่วไปเป็นหน่วยการสร้างที่คุณสามารถผสมและจับคู่ตามที่คุณต้องการมันจะช่วยให้คุณเรียนรู้วิธีการเขียนและดีบักรูปแบบของคุณเอง แต่ยังเข้าใจวิธีรูปแบบที่ผู้อื่นเขียน
แนวคิดการแสดงผลปกติที่ง่ายที่สุดคือตัวอักษร รูปแบบNตรงกับอักขระ 'N'
นิพจน์ปกติถัดจากลำดับการจับคู่ซึ่งกันและกัน ตัวอย่างเช่นรูปแบบที่Nickตรงกับลำดับ 'N' ตามด้วย 'i' ตามด้วย 'c' ตามด้วย 'k'
หากคุณเคยใช้grepกับ Unix - เพียงเพื่อค้นหาสตริงการค้นหาทั่วไป - คุณใช้นิพจน์ปกติอยู่แล้ว! ( reในgrepหมายถึงนิพจน์ทั่วไป)
เพิ่มความซับซ้อนเพียงเล็ก ๆ น้อย ๆ ที่คุณสามารถตรงกับทั้ง 'นิค' หรือ 'นิค' [Nn]ickกับรูปแบบ ส่วนในวงเล็บเหลี่ยมเป็นคลาสอักขระซึ่งหมายความว่าตรงกับหนึ่งในอักขระที่ล้อมรอบ นอกจากนี้คุณยังสามารถใช้ช่วงในคลาสของตัวละครดังนั้น[a-c]ตรงกับ 'a' หรือ 'b' หรือ 'c'
รูปแบบ.พิเศษ: มากกว่าตรงกับจุดที่แท้จริงเท่านั้นมันตรงกับใด ๆของตัวละคร† [-.?+%$A-Za-z0-9...]มันเป็นแนวคิดเดียวกับตัวอักษรระดับใหญ่จริงๆ
นึกถึงคลาสของตัวละครเป็นเมนู: เลือกเพียงอันเดียว
การใช้.ช่วยให้คุณประหยัดการพิมพ์จำนวนมากและมีทางลัดอื่น ๆ สำหรับรูปแบบทั่วไป สมมติว่าคุณต้องการจับคู่ตัวเลข: วิธีหนึ่งในการเขียนนั่นคือ[0-9]วิธีหนึ่งที่จะเขียนว่าเป็น ตัวเลขเป็นเป้าหมายการจับคู่บ่อยๆดังนั้นคุณสามารถใช้ทางลัดแทน\dได้ ส่วนอื่น ๆ คือ\s(ช่องว่าง) และ\w(ตัวอักษรคำ: ตัวอักษรและตัวเลขหรือขีดล่าง)
ตัวแปรที่เป็นตัวพิมพ์ใหญ่เป็นการเติมเต็มดังนั้น \Sจับคู่กับอักขระที่ไม่ใช่สีขาวใด ๆตัวอย่างเช่น
จากนั้นคุณสามารถทำซ้ำส่วนของรูปแบบของคุณกับปริมาณ ตัวอย่างเช่นรูปแบบab?cตรงกับ 'abc' หรือ 'ac' เนื่องจาก?ตัวขยายทำให้รูปแบบย่อยมีการแก้ไขทางเลือก ปริมาณอื่น ๆ
* (ศูนย์หรือมากกว่านั้น)+ (หนึ่งครั้งขึ้นไป){n}( nแน่นอนครั้ง){n,}(อย่างน้อยnครั้ง){n,m}(อย่างน้อยnครั้ง แต่ไม่เกินmครั้ง)ใส่บางส่วนของบล็อกเหล่านี้ร่วมกันแบบ[Nn]*ickตรงทั้งหมด
นัดแรกแสดงให้เห็นถึงบทเรียนสำคัญ: *ประสบความสำเร็จเสมอ!รูปแบบใด ๆ สามารถจับคู่กับศูนย์ครั้ง
ตัวอย่างที่มีประโยชน์อื่น ๆ :
[0-9]+ (และมันเทียบเท่า \d+ ) ตรงกับจำนวนเต็มใด ๆ ที่ไม่เป็นลบ\d{4}-\d{2}-\d{2} ตรงกับวันที่จัดรูปแบบเช่น 2019-01-01ปริมาณปรับเปลี่ยนรูปแบบไปทางซ้ายทันที คุณอาจคาดหวัง0abc+0เพื่อให้ตรงกับ '0abc0', '0abcabc0' และอื่น ๆ แต่รูปแบบทันทีcไปทางซ้ายของบวกปริมาณคือ ซึ่งหมายความว่า0abc+0ตรงกับ '0abc0', '0abcc0', '0abccc0' และอื่น ๆ
เพื่อให้ตรงกับหนึ่งหรือมากกว่าลำดับของ 'abc' 0(abc)+0ด้วยศูนย์ที่ปลายการใช้ วงเล็บแสดงรูปแบบย่อยที่สามารถวัดเป็นหน่วยได้ นอกจากนี้ยังเป็นเรื่องธรรมดาสำหรับเอ็นจิ้นนิพจน์ทั่วไปเพื่อบันทึกหรือ "จับ" ส่วนของข้อความอินพุตที่ตรงกับกลุ่มที่วงเล็บ การแตกบิตด้วยวิธีนี้มีความยืดหยุ่นมากกว่าและมีข้อผิดพลาดน้อยกว่าการนับดัชนีและsubstrสกัดบิตวิธีนี้มีความยืดหยุ่นมากขึ้นและข้อผิดพลาดน้อยกว่าดัชนีนับและ
ก่อนหน้านี้เราเห็นวิธีหนึ่งในการจับคู่ 'Nick' หรือ 'nick' Nick|nickอีกประการหนึ่งคือมีการสลับกันในขณะที่ โปรดจำไว้ว่าการสลับนั้นรวมทุกอย่างทางด้านซ้ายและทุกอย่างไปทางขวา ใช้การจัดกลุ่มวงเล็บที่จะ จำกัด ขอบเขตของ|, เช่น(Nick|nick) ,
สำหรับตัวอย่างอื่นคุณสามารถเขียน[a-c]เป็นa|b|cแต่ตอนนี้มีแนวโน้มที่จะก่อให้เกิดผลลัพธ์เพราะการใช้งานจำนวนมากถือว่าทางเลือกที่จะมีความยาวมากกว่า 1
แม้ว่าตัวละครบางตัวตรงกับตัวเอง แต่คนอื่น ๆ มีความหมายพิเศษ รูปแบบที่\d+ไม่ตรงกับทับขวาตามด้วยตัวพิมพ์เล็ก D \\d\+ตามด้วยเครื่องหมายบวกที่จะได้รับที่เราต้องการใช้ แบ็กสแลชจะลบความหมายพิเศษออกจากอักขระต่อไปนี้
ปริมาณการแสดงออกปกติมีความโลภ ซึ่งหมายความว่าพวกเขาจับคู่ข้อความให้มากที่สุดเท่าที่จะทำได้ในขณะที่ทำให้รูปแบบทั้งหมดตรงกัน
ตัวอย่างเช่นสมมติว่าอินพุตเป็น
"สวัสดี" เธอพูด "คุณสบายดีไหม"
คุณอาจคาดหวังว่า".+"จะจับคู่เฉพาะ 'สวัสดี' และจะประหลาดใจเมื่อคุณเห็นว่าตรงกับ 'สวัสดี' ตลอดเวลาผ่าน 'คุณ?'
หากต้องการเปลี่ยนจากความโลภเป็นสิ่งที่คุณคิดว่าระมัดระวังให้เพิ่มส่วนพิเศษ?เข้ากับปริมาณ ตอนนี้คุณเข้าใจแล้วว่า\((.+?)\)ตัวอย่างจากคำถามของคุณทำงานอย่างไร มันตรงกับลำดับของวงเล็บซ้ายที่แท้จริงตามด้วยอักขระหนึ่งตัวขึ้นไปและถูกยกเลิกด้วยวงเล็บขวา
หากอินพุตของคุณคือ '(123) (456)' การจับภาพแรกจะเป็น '123' ควอนตัมที่ไม่ใช่โลภต้องการอนุญาตให้ส่วนที่เหลือของรูปแบบเริ่มจับคู่โดยเร็วที่สุด
(สำหรับความสับสนของคุณฉันไม่รู้ภาษาถิ่นปกติที่((.+?))จะทำสิ่งเดียวกันฉันสงสัยว่ามีบางสิ่งบางอย่างหลงหายในการส่งสัญญาณไปที่ไหนสักแห่งระหว่างทาง)
ใช้รูปแบบพิเศษ^เพื่อจับคู่เฉพาะที่จุดเริ่มต้นของการป้อนข้อมูลของคุณและ$เพื่อจับคู่เฉพาะในตอนท้าย การทำ "หนังสือ" กับรูปแบบของคุณที่คุณพูดว่า "ฉันรู้ว่ามีอะไรอยู่ข้างหน้าและข้างหลัง แต่ให้ทุกอย่างระหว่างฉัน" เป็นเทคนิคที่มีประโยชน์
สมมติว่าคุณต้องการจับคู่ความคิดเห็นของแบบฟอร์ม
-- This is a comment --
^--\s+(.+)\s+--$คุณต้องการเขียน
นิพจน์ทั่วไปนั้นวนซ้ำดังนั้นเมื่อคุณเข้าใจกฎพื้นฐานเหล่านี้แล้วคุณสามารถรวมเข้าด้วยกันได้ตามต้องการ
†:ข้อความข้างต้นที่.ตรงกับตัวละครใด ๆ เป็นการทำให้เข้าใจง่ายสำหรับวัตถุประสงค์การสอนที่ไม่เป็นความจริงอย่างเคร่งครัด Dot จับคู่อักขระใด ๆ ยกเว้นการขึ้นบรรทัดใหม่"\n"แต่ในทางปฏิบัติคุณไม่ค่อยคาดหวังรูปแบบเช่น.+การข้ามขอบเขตการขึ้นบรรทัดใหม่ Perl regexes มี/sสวิตช์และ Java Pattern.DOTALLตัวอย่างเช่นเพื่อให้.ตรงกับตัวละครใด ๆ เลย สำหรับภาษาที่ไม่มีคุณลักษณะดังกล่าวคุณสามารถใช้สิ่งที่ต้องการ[\s\S]จับคู่ "ช่องว่างใด ๆ หรือช่องว่างที่ไม่ใช่" ในคำอื่น ๆ
a{,m}ไม่ได้เป็นอย่างน้อยใน Javascript, Perl และ Python