RegEx: 20 ขั้นตอนสั้นๆ เพื่อเชี่ยวชาญนิพจน์ทั่วไป ส่วนที่ 1 RegEx: 20 ขั้นตอนสั้นๆ เพื่อเชี่ยวชาญนิพจน์ทั่วไป ส่วนที่ 2: ในส่วนนี้ เราจะพูดถึงสิ่งที่ซับซ้อนกว่านี้เล็กน้อย แต่การควบคุมพวกมันเหมือนเมื่อก่อนจะไม่ใช่เรื่องยาก ฉันขอย้ำอีกครั้งว่าจริงๆ แล้ว RegEx นั้นง่ายกว่าที่คิดในตอนแรก และคุณไม่จำเป็นต้องเป็นนักวิทยาศาสตร์จรวดเพื่อที่จะเชี่ยวชาญและเริ่มใช้งานในทางปฏิบัติ ต้นฉบับภาษาอังกฤษของบทความนี้อยู่ที่นี่
ขั้นตอนที่ 11: วงเล็บ
ในปัญหาสุดท้าย เราค้นหาค่าจำนวนเต็มและค่าตัวเลขทศนิยม (จุด) ประเภทต่างๆ แต่กลไกของนิพจน์ทั่วไปไม่ได้แยกความแตกต่างระหว่างค่าทั้งสองประเภทนี้ เนื่องจากทุกอย่างถูกบันทึกไว้ในนิพจน์ทั่วไปขนาดใหญ่เพียงนิพจน์เดียว เราสามารถบอกเอ็นจิ้นนิพจน์ทั่วไปให้แยกความแตกต่างระหว่างการจับคู่ประเภทต่างๆ หากเราใส่รูปแบบย่อของเราไว้ในวงเล็บ:
คุณอาจประสบปัญหากับงานสุดท้าย หากคุณพยายามกำหนดให้ "นักดื่มที่ถูกกฎหมาย" เป็นกลุ่มจับกลุ่มแรกแทนที่จะเป็นกลุ่มที่สอง เพื่อให้เข้าใจว่าทำไม เรามาดูตัวอย่างอื่นกัน สมมติว่าเราต้องการบันทึกนามสกุลที่มีอักขระน้อยกว่า 4 ตัวและนามสกุลที่มีอักขระ 4 ตัวขึ้นไปแยกกัน มาตั้งชื่อให้สั้นลงให้กับกลุ่มจับภาพกลุ่มแรกและดูว่าเกิดอะไรขึ้น:
ขั้นตอนที่ 13: วงเล็บปีกกา
ในตัวอย่างที่มีนามสกุลจากขั้นตอนที่แล้ว เรามี 2 กลุ่มที่เกือบจะซ้ำกันในรูปแบบเดียว:
ขั้นตอนที่ 14:
งานสุดท้ายค่อนข้างยาก แต่ถ้าเราทำให้มันซับซ้อนขึ้นอีกหน่อยโดยการใส่รหัสผ่านในเครื่องหมายคำพูดขั้นตอนที่ 15: "คาเร็ต"
ลำดับขอบเขตของคำ
ขั้นตอนที่ 11: วงเล็บ()
เป็นการจับกลุ่ม
รูปแบบ: ([AZ])|([az]) string: ประธานาธิบดีคนปัจจุบันของโบลิเวียคือ Evo Morales ตรงกัน: ^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^ ^^ ^^^ ^^^^^^^ กลุ่ม: 122 2222222 122222222 22 1222222 22 122 1222222( ตัวอย่าง ) นิพจน์ทั่วไปข้างต้นกำหนดกลุ่มการจับภาพสองกลุ่มที่ได้รับการจัดทำดัชนีเริ่มต้นที่ 1 กลุ่มการจับภาพกลุ่มแรกตรงกับอักษรตัวพิมพ์ใหญ่ตัวเดียว และกลุ่มการจับภาพที่สองจะตรงกับตัวอักษรตัวพิมพ์เล็กตัวใดตัวหนึ่ง ด้วยการใช้เครื่องหมาย 'หรือ'
|
และวงเล็บ()
เป็นกลุ่มการจับ เราสามารถกำหนดนิพจน์ทั่วไปรายการเดียวที่ตรงกับสตริงหลายประเภท หากเราใช้สิ่งนี้กับ regex การค้นหาแบบยาว/ลอยจากส่วนก่อนหน้าของบทความ กลไก regex จะบันทึกการจับคู่ที่เกี่ยวข้องในกลุ่มที่เหมาะสม โดยการตรวจสอบว่าสตริงย่อยตรงกับกลุ่มใด เราสามารถระบุได้ทันทีว่าเป็นค่าทศนิยมหรือค่ายาว:
รูปแบบ: (\d*\.\d+[fF]|\d+\.\d*[fF]|\d+[fF])|(\d+[lL]) สตริง: 42L 12 x 3.4f 6l 3.3 0F LF .2F 0. ตรงกัน: ^^^ ^^^^ ^^ ^^ ^^^ กลุ่ม: 222 1111 22 11 111( ตัวอย่าง ) นิพจน์ทั่วไปนี้ค่อนข้างซับซ้อน และเพื่อให้เข้าใจได้ดีขึ้น เรามาดูรายละเอียดแต่ละรูปแบบกันดีกว่า:
( // ตรงกับสตริงย่อย "float" ใด ๆ \d*\.\d+[fF] | \d+\.\d*[fF] | \d+[เอฟเอฟ] ) | // หรือ ( // ตรงกับสตริงย่อย "ยาว" ใด ๆ \d+[ลิตร] )เครื่องหมาย
|
และกลุ่มการจับในวงเล็บ()
ช่วยให้เราจับคู่สตริงย่อยประเภทต่างๆ ได้ ในกรณีนี้ เรากำลังจับคู่ตัวเลขทศนิยม "float" หรือจำนวนเต็มยาว "long"
( \d*\.\d+[fF] // 1+ หลักทางด้านขวาของจุดทศนิยม | \d+\.\d*[fF] // 1+ หลักทางด้านซ้ายของจุดทศนิยม | \d+[fF] // ไม่มีจุด มีเพียง 1+ หลักเท่านั้น ) | ( \d+[lL] // ไม่มีจุด มีเพียง 1+ หลักเท่านั้น )ในกลุ่มการจับแบบ "ลอย" เรามีสามตัวเลือก: ตัวเลขที่มีจุดทศนิยมอย่างน้อย 1 หลักทางด้านขวาของจุดทศนิยม ตัวเลขที่มีจุดทศนิยมด้านซ้ายอย่างน้อย 1 หลัก และตัวเลขที่ไม่มีจุดทศนิยม รายการใดรายการหนึ่งเป็นแบบ "ลอย" ตราบใดที่มีตัวอักษร "f" หรือ "F" ต่อท้าย ภายในกลุ่มการจับแบบ "ยาว" เรามีทางเลือกเดียวเท่านั้น - เราต้องมีตัวเลข 1 หลักขึ้นไปตามด้วยอักขระ "l" หรือ "L" เอ็นจิ้นนิพจน์ทั่วไปจะค้นหาสตริงย่อยเหล่านี้ในสตริงที่กำหนดและจัดทำดัชนีให้อยู่ในกลุ่มการจับที่เหมาะสม บันทึกว่าเราไม่จับคู่ตัวเลขใดๆ ที่ไม่มี "l", "L", "f" หรือ "F" เพิ่มเข้าไป ควรจำแนกตัวเลขเหล่านี้อย่างไร? ถ้ามีจุดทศนิยม ภาษา Java จะมีค่าเริ่มต้นเป็น "สองเท่า" ไม่เช่นนั้นจะต้องเป็น "int"
มารวบรวมสิ่งที่เราได้เรียนรู้ด้วยปริศนาสองสามข้อ:
เพิ่มกลุ่มการบันทึกอีกสองกลุ่มใน regex ด้านบนเพื่อแยกประเภทตัวเลขสองเท่าหรือ int ด้วย (นี่เป็นคำถามที่ยุ่งยากอีกข้อหนึ่ง อย่าเพิ่งท้อแท้หากต้องใช้เวลาสักครู่ เป็นวิธีสุดท้ายที่จะเห็นวิธีแก้ปัญหาของฉัน)ลวดลาย: string: 42L 12 x 3.4f 6l 3.3 0F LF .2F 0. ไม้ขีดไฟ: ^^^ ^^ ^^^^ ^^ ^^^ ^^ ^^^ ^^ กลุ่ม: 333 44 1111 33 222 11 111 22( วิธีแก้ไข ) ปัญหาต่อไปจะง่ายขึ้นเล็กน้อย ใช้กลุ่มการจับในวงเล็บ
()
เครื่องหมาย 'หรือ' |
และช่วงอักขระเพื่อจัดเรียงอายุต่อไปนี้: "ถูกกฎหมายสำหรับการดื่มในสหรัฐอเมริกา" (>= 21) และ "ไม่ได้รับอนุญาตให้ดื่มในประเทศสหรัฐอเมริกา" (<21):
ลวดลาย: สาย: 7 10 17 18 19 20 21 22 23 24 30 40 100 120 ตรงกัน: ^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ กลุ่ม: 2 22 22 22 22 22 11 11 11 11 11 11 111 111( สารละลาย )
ขั้นตอนที่ 12: ระบุการจับคู่ที่เฉพาะเจาะจงมากขึ้นก่อน

รูปแบบ: ([AZ][az]?[az]?)|([AZ][az][az][az]+) สตริง: Kim Job s Xu Clo yd Moh r Ngo Roc k. ตรงกัน: ^^^ ^^^ ^^ ^^^ ^^^ ^^^ ^^^ กลุ่ม: 111 111 11 111 111 111 111( ตัวอย่าง ) ตามค่าเริ่มต้น เอ็นจิ้นนิพจน์ทั่วไปส่วนใหญ่ใช้การจับคู่ที่ละโมบกับอักขระพื้นฐานที่เราเคยเห็นมา ซึ่งหมายความว่าเอ็นจิ้นนิพจน์ทั่วไปจะจับกลุ่มที่ยาวที่สุดที่กำหนดไว้โดยเร็วที่สุดในนิพจน์ทั่วไปที่ให้ไว้ ดังนั้นในขณะที่กลุ่มที่สองข้างต้นสามารถจับอักขระได้มากขึ้นในชื่อ เช่น "จ็อบส์" และ "คลาวด์" เป็นต้น แต่เนื่องจากอักขระสามตัวแรกของชื่อเหล่านั้นถูกจับโดยกลุ่มจับแรกแล้ว จึงไม่สามารถจับได้อีกในวินาที . ตอนนี้เรามาทำการแก้ไขเล็กๆ น้อยๆ - เพียงเปลี่ยนลำดับของกลุ่มการจับ โดยวางกลุ่มที่เฉพาะเจาะจงมากขึ้น (ยาวกว่า) ก่อน:
รูปแบบ: ([AZ][az][az][az]+)|([AZ][az]?[az]?)สตริง : Kim Jobs Xu Cloyd Mohr Ngo Rock ตรงกัน: ^^^ ^^^^ ^^ ^^^^^ ^^^^ ^^^ ^^^^ กลุ่ม: 222 1111 22 11111 1111 222 1111( ตัวอย่าง )
ภารกิจ...ครั้งนี้มีเพียงหนึ่งเดียวเท่านั้น :)
รูปแบบที่ "เจาะจงมากขึ้น" มักจะหมายถึง "ยาวขึ้น" เสมอ สมมติว่าเราต้องการค้นหา "คำ" สองประเภท: ประเภทแรกคือคำที่ขึ้นต้นด้วยสระ (โดยเฉพาะ) จากนั้นอีกประเภทที่ไม่ขึ้นต้นด้วยสระ (คำอื่นใด) ลองเขียนนิพจน์ทั่วไปเพื่อบันทึกและระบุสตริงที่ตรงกับสองกลุ่มนี้ (กลุ่มด้านล่างนี้ใช้ตัวอักษรแทนตัวเลข คุณต้องพิจารณาว่ากลุ่มใดควรตรงกับกลุ่มแรกและกลุ่มใดตรงกับกลุ่มที่สอง)ลวดลาย: สตริง: pds6f uub 24r2gp ewqrty l ui_op ตรงกัน: ^^^^^ ^^^ ^^^^^^ ^^^^^^ ^ ^^^^^ กลุ่ม: NNNNN VVV NNNNNN VVVVVV N VVVVV( วิธีแก้ไข ) โดยทั่วไป ยิ่งนิพจน์ทั่วไปของคุณแม่นยำมากเท่าใด นิพจน์ทั่วไปก็จะยิ่งใช้เวลานานขึ้นเท่านั้น และยิ่งแม่นยำมากเท่าไร โอกาสที่คุณจะจับภาพสิ่งที่คุณไม่ต้องการก็จะน้อยลงเท่านั้น ดังนั้นแม้ว่ามันอาจจะดูน่ากลัว แต่ regexes ที่ยาวขึ้น ~= regexes ที่ดีกว่า น่าเสียดาย .
ขั้นตอนที่ 13: วงเล็บปีกกา{}
ตามจำนวนการทำซ้ำที่กำหนด

รูปแบบ: ([AZ][az][az][az]+)|([AZ][az]?[az]?)สตริง : Kim Jobs Xu Cloyd Mohr Ngo Rock ตรงกัน: ^^^ ^^^^ ^^ ^^^^^ ^^^^ ^^^ ^^^^ กลุ่ม: 222 1111 22 11111 1111 222 1111สำหรับกลุ่มแรก เราต้องการนามสกุลที่มีตัวอักษรสี่ตัวขึ้นไป กลุ่มที่สองต้องจับนามสกุลที่มีตัวอักษรสามตัวหรือน้อยกว่านั้น มีวิธีที่ง่ายกว่าในการเขียนสิ่งนี้มากกว่าการทำซ้ำ
[a-z]
กลุ่มเหล่านี้ซ้ำแล้วซ้ำอีกหรือไม่? มีอยู่หากคุณใช้เครื่องหมายปีกกาสำหรับสิ่ง{}
นี้ วงเล็บปีกกา{}
ช่วยให้เราระบุจำนวนการจับคู่ขั้นต่ำและ (เป็นทางเลือก) สูงสุดของอักขระก่อนหน้าหรือกลุ่มแคปเจอร์ได้ มีกรณีการใช้งานสามกรณี{}
:
{X} // ตรงกับ X ครั้งทุกประการ {X,} // ตรงกัน >= X ครั้ง {X,Y} // จับคู่ >= X และ <= Y ครั้งนี่คือตัวอย่างของไวยากรณ์ที่แตกต่างกันทั้งสามนี้:
รูปแบบ: [az]{11} สตริง: humuhumunuk unukuapua'a การแข่งขัน: ^^^^^^^^^^^( ตัวอย่าง )
รูปแบบ: [az]{18,} สตริง: humuhumunukunukuapua 'a. การแข่งขัน: ^^^^^^^^^^^^^^^^^^^^^( ตัวอย่าง )
รูปแบบ: [az]{11,18} สตริง: humuhumunukunukuap ua'a การแข่งขัน: ^^^^^^^^^^^^^^^^^^( ตัวอย่าง ) มีหลายประเด็นที่ควรทราบในตัวอย่างข้างต้นบันทึก:. ขั้นแรก เมื่อใช้สัญลักษณ์ {X} อักขระหรือกลุ่มก่อนหน้าจะจับคู่ตัวเลข (X) คูณทุกประการ หากมีอักขระใน "คำ" มากกว่า (มากกว่าตัวเลข X) ที่สามารถตรงกับรูปแบบได้ (ดังแสดงในตัวอย่างแรก) อักขระเหล่านั้นจะไม่ถูกรวมไว้ในการจับคู่ หากจำนวนอักขระน้อยกว่า X การจับคู่ทั้งหมดจะล้มเหลว (ลองเปลี่ยน 11 เป็น 99 ในตัวอย่างแรก) ประการที่สอง สัญกรณ์ {X,} และ {X,Y} เป็นสัญลักษณ์โลภ พวกเขาจะพยายามจับคู่อักขระให้ได้มากที่สุดเท่าที่จะเป็นไปได้ในขณะที่ยังคงพึงพอใจกับนิพจน์ทั่วไปที่กำหนด หากคุณระบุ {3,7} จะสามารถจับคู่อักขระได้ 3 ถึง 7 ตัว และหากอักขระ 7 ตัวถัดไปถูกต้อง ระบบจะจับคู่อักขระทั้ง 7 ตัว หากคุณระบุ {1,} และตรงกับอักขระ 14,000 ตัวถัดไปทั้งหมด อักขระเหล่านั้นทั้ง 14,000 ตัวจะรวมอยู่ในสตริงที่เกี่ยวข้อง เราจะใช้ความรู้นี้เขียนนิพจน์ข้างต้นใหม่ได้อย่างไร การปรับปรุงที่ง่ายที่สุดอาจเป็นการแทนที่กลุ่มใกล้เคียง
[a-z]
ด้วย[a-z]{N}
โดยที่ N จะถูกเลือกตามลำดับ:
รูปแบบ: ([AZ][az]{2}[az]+)|([AZ][az]?[az]?)
...แต่นั่นไม่ได้ทำให้อะไรดีขึ้นมากนัก ดูกลุ่มการจับกลุ่มแรก: เรามี[a-z]{2}
(ซึ่งตรงกับตัวอักษรพิมพ์เล็ก 2 ตัวพอดี) ตามด้วย[a-z]+
(ซึ่งตรงกับตัวอักษรพิมพ์เล็ก 1 ตัวขึ้นไป) เราสามารถทำให้สิ่งนี้ง่ายขึ้นโดยขอให้ใช้อักษรตัวพิมพ์เล็ก 3 ตัวขึ้นไปโดยใช้เครื่องหมายปีกกา:
รูปแบบ: ([AZ][az]{3,})|([AZ][az]?[az]?)
กลุ่มการจับที่สองนั้นแตกต่างออกไป เราจำเป็นต้องมีอักขระไม่เกินสามตัวในนามสกุลเหล่านี้ ซึ่งหมายความว่าเรามีขีดจำกัดบน แต่ขีดจำกัดล่างของเราคือศูนย์:
รูปแบบ: ([AZ][az]{3,})|([AZ][az]{0,2})
ความเฉพาะเจาะจงจะดีกว่าเสมอเมื่อใช้นิพจน์ทั่วไป ดังนั้นจึงควรหยุดเพียงแค่นั้น แต่ฉันอดไม่ได้ที่จะสังเกตว่าช่วงอักขระทั้งสองนี้ ( [AZ]
และ[az]
) ที่อยู่ติดกันดูเหมือนคลาส "อักขระคำ" \w
( [A-Za-z0-9_]
) . หากเรามั่นใจว่าข้อมูลของเรามีเฉพาะนามสกุลที่มีรูปแบบที่ดี เราก็สามารถทำให้นิพจน์ทั่วไปของเราง่ายขึ้นและเขียนง่ายๆ:
รูปแบบ: (\w{4,})|(\w{1,3})
กลุ่มแรกจับลำดับใดๆ ที่มี "อักขระคำ" 4 ตัวขึ้นไป ( [A-Za-z0-9_]
) และกลุ่มที่สองจับลำดับใดๆ ที่มี "อักขระคำ" ตั้งแต่ 1 ถึง 3 ตัว (รวม) มันจะได้ผลไหม?
รูปแบบ: (\w{4,})|(\w{1,3}) สตริง: Kim Jobs Xu Cloyd Mohr Ngo Rock ตรงกัน: ^^^ ^^^^ ^^ ^^^^^ ^^^^ ^^^ ^^^^ กลุ่ม: 222 1111 22 11111 1111 222 1111( ตัวอย่าง ) มันได้ผล! แนวทางนี้เป็นอย่างไร? และมันสะอาดกว่าตัวอย่างก่อนหน้านี้มาก เนื่องจากกลุ่มการจับกลุ่มแรกตรงกับนามสกุลทั้งหมดที่มีอักขระสี่ตัวขึ้นไป เราจึงสามารถเปลี่ยนกลุ่มการจับกลุ่มที่สองเป็นแบบง่ายๆ ได้
\w+
เนื่องจากจะทำให้เราสามารถจับนามสกุลที่เหลือทั้งหมด (ที่มีอักขระ 1, 2 หรือ 3 ตัว):
รูปแบบ: (\w{4,})|(\w+) สตริง: Kim Jobs Xu Cloyd Mohr Ngo Rock ตรงกัน: ^^^ ^^^^ ^^ ^^^^^ ^^^^ ^^^ ^^^^ กลุ่ม: 222 1111 22 11111 1111 222 1111( ตัวอย่าง )
มาช่วยให้สมองเรียนรู้สิ่งนี้และแก้ไขปัญหา 2 ข้อต่อไปนี้:
ใช้เครื่องหมายปีกกา{}
เพื่อเขียนนิพจน์ทั่วไปการค้นหาหมายเลขประกันสังคมจากขั้นตอนที่ 7 ใหม่:
ลวดลาย: สายอักขระ: 113-25=1902 182-82-0192 H23-_3-9982 1I1-O0-E38B การแข่งขัน: ^^^^^^^^^^^( วิธีแก้ไข ) สมมติว่าตัวตรวจสอบความแข็งแกร่งของรหัสผ่านของเว็บไซต์กำหนดให้รหัสผ่านของผู้ใช้มีความยาวระหว่าง 6 ถึง 12 อักขระ เขียนนิพจน์ทั่วไปที่ทำเครื่องหมาย รหัสผ่าน ที่ไม่ถูกต้องในรายการด้านล่าง รหัสผ่านแต่ละอันอยู่ในวงเล็บ
()
เพื่อให้จับคู่ได้ง่าย ดังนั้น ตรวจสอบให้แน่ใจว่านิพจน์ทั่วไปขึ้นต้นและลงท้ายด้วยอักขระ ตามตัวอักษร (
และ สัญลักษณ์ )
คำแนะนำ: ตรวจสอบให้แน่ใจว่าคุณไม่อนุญาตให้ใช้วงเล็บตามตัวอักษรในรหัสผ่านที่มี[^()]
หรือคล้ายกัน ไม่เช่นนั้น คุณจะจับคู่สตริงทั้งหมด!
ลวดลาย: สตริง: (12345) (รหัสผ่านของฉัน) (Xanadu.2112) (su_do) (ของพนักงานขาย!) การแข่งขัน: ^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^( สารละลาย )
ขั้นตอนที่ 14: \b
สัญลักษณ์เส้นขอบความกว้างเป็นศูนย์

""
แทนวงเล็บล่ะ()
? เราสามารถเขียนวิธีแก้ปัญหาที่คล้ายกันโดยแทนที่อักขระในวงเล็บทั้งหมดด้วยเครื่องหมายคำพูดได้หรือไม่
รูปแบบ: \"[^"]{0.5}\"|\"[^"]+\s[^"]*\" string: "12345" "รหัสผ่านของฉัน" "Xanadu.2112 " " su_do" " OfSalesmen! " การแข่งขัน: ^^^^^^^ ^^^^^^^^^^^^^ ^^^ ^^^( ตัวอย่าง ) มันไม่ได้ออกมาน่าประทับใจมากนัก คุณเคยเดาแล้วว่าทำไม? ปัญหาคือเรากำลังมองหารหัสผ่านที่ไม่ถูกต้องที่นี่ "Xanadu.2112" เป็นรหัสผ่านที่ดี ดังนั้นเมื่อ regex พบว่าลำดับนี้ไม่มีการเว้นวรรคหรืออักขระตามตัว
"
อักษร มันจะให้ไว้หน้าอักขระ"
ที่รับรองรหัสผ่านทางด้านขวา (เนื่องจากเราระบุว่า"
ไม่พบอักขระในรหัสผ่านโดยใช้[^"]
) เมื่อเอ็นจิ้นนิพจน์ทั่วไปพอใจแล้วว่าอักขระเหล่านั้นไม่ตรงกับนิพจน์ทั่วไป ระบบจะทำงานอีกครั้งในตำแหน่งที่ค้างไว้ - ตำแหน่งที่อักขระอยู่"
ซึ่งจำกัด " Xanadu.2112" ด้านขวา. จากนั้นเขาเห็นตัวละครอวกาศตัวหนึ่งและตัวละครอีกตัว"
- สำหรับเขานี่คือรหัสผ่านที่ผิด! โดยพื้นฐานแล้ว เขาพบลำดับนี้" "
และเดินหน้าต่อไป นี่ไม่ใช่สิ่งที่เราอยากได้เลย... คงจะดีถ้าเราระบุได้ว่าอักขระตัวแรกของรหัสผ่านไม่ ควร เว้นวรรค มีวิธีการทำเช่นนี้หรือไม่? (ถึงตอนนี้คุณคงรู้แล้วว่าคำตอบสำหรับคำถามเชิงวาทศิลป์ทั้งหมดของฉันคือ "ใช่") ใช่! มีวิธีดังกล่าว! \b
เอ็นจินนิพจน์ทั่วไปจำนวนมาก มีลำดับการหลีก เช่น "ขอบเขตคำ" "ขอบเขตของคำ" \b
คือลำดับการหลีกที่มีความกว้างเป็นศูนย์ ซึ่งค่อนข้างจะตรงกับขอบเขตของคำ โปรดจำไว้ว่าเมื่อเราพูด ว่า"คำ" เราหมายถึงลำดับของอักขระในชั้นเรียน\w
หรือ [A-Za-z0-9_]
การจับคู่ขอบเขตคำหมายความว่าอักขระที่อยู่ข้างหน้าหรือหลังลำดับ\b
จะต้องเป็นне
อักขระคำ อย่างไรก็ตาม เมื่อจับคู่ เราจะไม่รวมอักขระนี้ในสตริงย่อยที่บันทึกไว้ นี่คือความกว้างเป็นศูนย์ หากต้องการดูวิธีการทำงาน โปรดดูตัวอย่างเล็กๆ น้อยๆ:
รูปแบบ: \b [ ^ ]+\b string : ยังคงต้องการเงิน Lebowski การแข่งขัน: ^^ ^^^^^ ^^^^ ^^ ^^^^^ ^^^^^^^^( ตัวอย่าง ) ลำดับ
[^ ]
จะต้องตรงกับอักขระใดๆ ที่ไม่ใช่อักขระช่องว่างตามตัวอักษร เหตุใดจึงไม่ตรงกับเครื่องหมายจุลภาค,
หลังเงินหรือจุด " .
ตามหลัง Lebowski เนื่องจากเครื่องหมายจุลภาค,
และจุด.
ไม่ใช่อักขระคำ จึงสร้างขอบเขตระหว่างอักขระคำและอักขระที่ไม่ใช่คำ โดยปรากฏระหว่างy
ส่วนท้ายของอักขระ คำว่า เงิน และลูกน้ำ,
ที่ตามมา และระหว่าง " i
คำว่า Lebowski กับจุด.
(จุด/จุด) ที่ตามมา นิพจน์ทั่วไปจะจับคู่กับขอบเขตของคำเหล่านี้ (แต่ไม่ใช่กับอักขระที่ไม่ใช่คำที่ช่วยกำหนดเท่านั้น) แต่จะเกิดอะไรขึ้นหากเราไม่รวมความสอดคล้องไว้\b
ในเทมเพลตของเรา
รูปแบบ: [^ ]+ สตริง: ฉันยังคงต้องการเงิน Lebowski การแข่งขัน: ^^ ^^^^^ ^^^^ ^^ ^^^^^^ ^^^^^^^^^( ตัวอย่าง ) ใช่แล้ว ตอนนี้เราพบเครื่องหมายวรรคตอนเหล่านี้แล้ว ตอนนี้เรามาใช้ขอบเขตของคำเพื่อแก้ไข regex สำหรับรหัสผ่านที่ยกมา:
รูปแบบ: \"\b[^"]{0.5}\b\"|\"\b[^"]+\s[^"]*\b\" string: "12345" "mypassword" " Xanadu. 2112" "su_do" "ของนักขาย!" การแข่งขัน: ^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^( ตัวอย่าง ) โดยการใส่ขอบเขตคำไว้ในเครื่องหมายคำพูด ("\b ... \b") เรากำลังบอกได้อย่างมีประสิทธิภาพว่าอักขระตัวแรกและตัวสุดท้ายของรหัสผ่านที่ตรงกันจะต้องเป็น "อักขระคำ" ดังนั้นวิธีนี้ใช้ได้ดีที่นี่ แต่จะใช้งานไม่ได้หากอักขระตัวแรกหรือตัวสุดท้ายของรหัสผ่านของผู้ใช้ไม่ใช่อักขระคำ:
รูปแบบ: \"\b[^"]{0.5}\b\"|\"\b[^"]+\s[^"]*\b\"
สตริง: "รหัสผ่านต่อไปนี้istooshort" "C ++"
การแข่งขัน:
( ตัวอย่าง ) ดูว่ารหัสผ่านที่สองไม่ได้ทำเครื่องหมายว่า "ไม่ถูกต้อง" แม้ว่าจะสั้นเกินไปอย่างชัดเจนก็ตาม คุณจะต้องเป็นระมัดระวังด้วยลำดับ\b
เนื่องจากจะจับคู่เฉพาะขอบเขตระหว่างอักขระเท่านั้น\w
ไม่ใช่ \w
ในตัวอย่างข้างต้น เนื่องจากเราอนุญาตให้ใช้อักขระที่ไม่ ในรหัสผ่าน\w
ขอบเขตระหว่างอักขระ ตัวแรก/ตัว สุดท้าย \
ของรหัสผ่านจึงไม่รับประกันว่าเป็นขอบเขตของคำ\b
เพื่อให้ขั้นตอนนี้เสร็จสมบูรณ์ เราจะแก้ไขปัญหาง่ายๆ เพียงปัญหาเดียวเท่านั้น:
ขอบเขตของคำมีประโยชน์ในกลไกการเน้นไวยากรณ์เมื่อเราต้องการจับคู่ลำดับอักขระเฉพาะ แต่ต้องการให้แน่ใจว่าจะเกิดขึ้นที่จุดเริ่มต้นหรือจุดสิ้นสุดของคำเท่านั้น (หรือด้วยตัวมันเอง) สมมติว่าเรากำลังเขียนการเน้นไวยากรณ์และต้องการเน้นคำว่า var แต่เฉพาะเมื่อมันปรากฏด้วยตัวเองเท่านั้น (โดยไม่ต้องแตะอักขระอื่นในคำนั้น) คุณสามารถเขียนนิพจน์ทั่วไปสำหรับสิ่งนี้ได้หรือไม่? แน่นอนคุณทำได้ มันเป็นงานที่เรียบง่ายมาก ;)ลวดลาย: สตริง: var varx _var ( var j) barvarcar * var var -> { var } ตรงกัน: ^^^ ^^^ ^^^ ^^^ ^^^( สารละลาย )
ขั้นตอนที่ 15: "คาเร็ต" ^
เป็น "จุดเริ่มต้นของบรรทัด" และเครื่องหมายดอลลาร์$
เป็น "สิ้นสุดบรรทัด"

\b
(จากขั้นตอนสุดท้ายของส่วนก่อนหน้าของบทความ) ไม่ใช่ลำดับความกว้างเป็นศูนย์พิเศษเพียงลำดับเดียวที่พร้อมใช้งานในนิพจน์ทั่วไป สองรายการที่ได้รับความนิยมมากที่สุดคือ "คาเร็ต" ^
- "จุดเริ่มต้นของบรรทัด" และเครื่องหมายดอลลาร์$
- "สิ้นสุดบรรทัด" การรวมหนึ่งในนิพจน์ทั่วไปของคุณหมายความว่ารายการที่ตรงกันจะต้องปรากฏที่จุดเริ่มต้นหรือจุดสิ้นสุดของสตริงต้นฉบับ:
รูปแบบ: ^start|end$ string: start end start end start end start end ตรงกัน: ^^^^^ ^^^( ตัวอย่าง ) หากสตริงของคุณมีการขึ้นบรรทัดใหม่ มัน
^start
จะจับคู่ลำดับ "เริ่มต้น" ที่จุดเริ่มต้นของบรรทัดใดๆ และend$
จะจับคู่ลำดับ "สิ้นสุด" ที่ท้ายบรรทัดใดๆ (แม้ว่าจะแสดงได้ยากที่นี่ก็ตาม) สัญลักษณ์เหล่านี้มีประโยชน์อย่างยิ่งเมื่อทำงานกับข้อมูลที่มีตัวคั่น กลับไปที่ปัญหา "ขนาดไฟล์" จากขั้นตอนที่ 9 โดยใช้^
"จุดเริ่มต้นของบรรทัด" ในตัวอย่างนี้ ขนาดไฟล์ของเราจะถูกคั่นด้วยช่องว่าง "
" ดังนั้นเราจึงต้องการให้แต่ละขนาดไฟล์เริ่มต้นด้วยตัวเลข นำหน้าด้วยอักขระเว้นวรรคหรือจุดเริ่มต้นของบรรทัด:
รูปแบบ: (^| )(\d+|\d+\.\d+)[KMGT]Bสตริง : 6.6KB 1..3KB 12KB 5G 3.3MB KB .6.2TB 9MB ตรงกัน: ^^^^^ ^^^^^ ^^^^^^ ^^^^ กลุ่ม: 222 122 1222 12( ตัวอย่าง ) เราใกล้ถึงเป้าหมายแล้ว! แต่คุณอาจสังเกตเห็นว่าเรายังคงมีปัญหาเล็กๆ น้อยๆ อยู่ประการหนึ่ง นั่นคือ เรากำลังจับคู่อักขระเว้นวรรคก่อนขนาดไฟล์ที่ถูกต้อง ตอนนี้เราสามารถเพิกเฉยต่อกลุ่มการจับภาพนี้ (1) เมื่อเอ็นจิ้นนิพจน์ทั่วไปของเราพบมัน หรือเราสามารถใช้กลุ่มที่ไม่ได้จับภาพ ซึ่งเราจะเห็นในขั้นตอนถัดไป
ในระหว่างนี้เรามาแก้ไขปัญหาโทนเสียงอีก 2 ข้อ:
ดำเนินการต่อด้วยตัวอย่างการเน้นไวยากรณ์ของเราจากขั้นตอนสุดท้าย การเน้นไวยากรณ์บางส่วนจะทำเครื่องหมายช่องว่างต่อท้าย ซึ่งก็คือช่องว่างใดๆ ที่อยู่ระหว่างอักขระที่ไม่ใช่ช่องว่างและจุดสิ้นสุดของบรรทัด คุณสามารถเขียน regex เพื่อเน้นเฉพาะช่องว่างต่อท้ายได้หรือไม่?ลวดลาย:
สตริง: myvec <- c(1, 2, 3, 4, 5)
ตรงกัน: ^^^^^^^
( โซลูชัน ) ตัวแยกวิเคราะห์ค่าที่คั่นด้วยเครื่องหมายจุลภาค (CSV) แบบธรรมดาจะค้นหา "โทเค็น" ที่คั่นด้วยเครื่องหมายจุลภาค ""
โดยทั่วไป ช่อง ว่างจะไม่มีความหมายเว้นแต่จะอยู่ในเครื่องหมายคำพูด เขียนนิพจน์ทั่วไปในการแยกวิเคราะห์ CSV อย่างง่ายที่จับคู่โทเค็นระหว่างเครื่องหมายจุลภาค แต่ละเว้น (ไม่ได้บันทึก) ช่องว่างที่ไม่ได้ อยู่ ระหว่างเครื่องหมายคำพูด
ลวดลาย: สตริง: a, "b", "c d",e,f, "g h", dfgi,, k, "", l ตรงกับ: ^^ ^^^^ ^^^^^^^^^^ ^^^ ^^^ ^^^^^^ ^^ ^^^ ^ กลุ่ม: 21 2221 2222212121 222221 222211 21 221 2( โซลูชัน ) RegEx: 20 ขั้นตอนสั้น ๆ เพื่อเชี่ยวชาญนิพจน์ทั่วไป ตอนที่ 4
GO TO FULL VERSION