RegEx: 20 ขั้นตอนสั้นๆ เพื่อเชี่ยวชาญนิพจน์ทั่วไป ส่วนที่ 1 ต้นฉบับที่นี่ ในส่วนสุดท้าย เราเชี่ยวชาญนิพจน์ทั่วไปที่ง่ายที่สุด และได้เรียนรู้บางอย่างไปแล้ว ในส่วนนี้เราจะศึกษาการออกแบบที่ซับซ้อนมากขึ้นเล็กน้อย แต่เชื่อฉันเถอะว่ามันจะไม่ยากอย่างที่คิด
เอาล่ะมาทำต่อ!
ขั้นตอนที่ 8: เครื่องหมายดาว
จนถึงตอนนี้ เราสามารถจับคู่สตริงที่มีความยาวที่กำหนดได้มากหรือน้อยเท่านั้น แต่ในปัญหาล่าสุด เราได้เข้าใกล้ขีดจำกัดของสิ่งที่เราสามารถทำได้ด้วยสัญลักษณ์ที่เราเคยเห็นมา ตัวอย่างเช่น สมมติว่าเราไม่ได้จำกัดอยู่เพียงตัวระบุ Java 3 อักขระ แต่เราสามารถมีตัวระบุที่มีความยาวเท่าใดก็ได้ โซลูชันที่อาจได้ผลในตัวอย่างก่อนหน้านี้จะไม่ทำงานในตัวอย่างต่อไปนี้:
ขั้นตอนที่ 9: เครื่องหมายคำถาม "ไม่บังคับ"
คุณได้เขียน regex เพื่อแก้ไขปัญหาล่าสุดแล้วหรือยัง? มันได้ผลเหรอ? ตอนนี้ลองใช้มันที่นี่:
ขั้นตอนที่ 10: เครื่องหมาย "หรือ"
ในขั้นตอนที่ 8 เราประสบปัญหาในการค้นหาตัวเลขทศนิยมประเภทต่างๆ:
ขั้นตอนที่ 8: เครื่องหมายดาว*
และเครื่องหมายบวก+
รูปแบบ: [a-zA-Z_$]\w\w สตริง: __e $12 3 3.2 สำหรับบาร์ r a23 mm ab x ตรงกัน: ^^^ ^^^ ^^^ ^^^( ตัวอย่าง ) บันทึกว่าเมื่อตัวระบุถูกต้องแต่ยาวเกิน 3 ตัวอักษร ระบบจะจับคู่เฉพาะอักขระสามตัวแรกเท่านั้น และเมื่อตัวระบุถูกต้อง แต่มีอักขระน้อยกว่า 3 ตัว regex จะไม่พบเลย! ปัญหาคือนิพจน์ในวงเล็บ
[]
ตรงกับอักขระเพียงตัวเดียว เช่นเดียวกับคลาสอักขระ เช่น\w
. ซึ่งหมายความว่าการจับคู่ใดๆ ในนิพจน์ทั่วไปข้างต้นจะต้องมีความยาวสามอักขระพอดี มันเลยไม่ได้ผลดีอย่างที่เราหวังไว้ *
อักขระพิเศษ และสามารถช่วยได้ที่+
นี่ สิ่งเหล่านี้คือตัวปรับแต่งที่สามารถเพิ่มทางด้านขวาของนิพจน์ใดๆ เพื่อให้ตรงกับนิพจน์นั้นได้มากกว่าหนึ่งครั้ง ดาว Kleene (หรือ "เครื่องหมายดอกจัน") *
จะระบุว่าโทเค็นก่อนหน้าจะต้องจับคู่จำนวนครั้งเท่าใดก็ได้ รวมถึงศูนย์ครั้งด้วย เครื่องหมายบวก+
จะระบุว่าคุณต้องค้นหาอย่างน้อยหนึ่งครั้ง ดังนั้น นิพจน์ที่นำหน้าถือ+
เป็นข้อบังคับ (อย่างน้อยหนึ่งครั้ง) ในขณะที่นิพจน์ที่นำหน้า*
เป็นทางเลือก แต่เมื่อปรากฏขึ้น ก็สามารถปรากฏกี่ครั้งก็ได้ ตอนนี้ ด้วยความรู้นี้ เราสามารถแก้ไขนิพจน์ทั่วไปข้างต้นได้:
รูปแบบ: [a-zA-Z_$]\w* สตริง: __e $123 3.2 สำหรับ Barr a23mm ab x ตรงกัน: ^^^ ^^^^ ^^ ^^^^ ^^^^^ ^^ ^( ตัวอย่าง ) ตอนนี้เราจับคู่ตัวระบุที่ถูกต้องทุกความยาวแล้ว! บิงโก! แต่จะเกิดอะไรขึ้นถ้าเราใช้ ?
+
แทน*
?
รูปแบบ: [a-zA-Z_$]\w+ สตริง: __e $123 3.2 สำหรับ Barr a23mm ab x ตรงกัน: ^^^ ^^^^ ^^ ^^^^ ^^^^^ ^^( ตัวอย่าง
х
) เราพลาดนัดที่แล้ว เนื่องจากต้องมี+
อักขระอย่างน้อยหนึ่งตัวจึงจะตรงกันได้ แต่เนื่องจากนิพจน์ในวงเล็บ[]
ที่อยู่ข้างหน้า\w+
ได้ 'กิน' อักขระนั้นแล้วx
จึงไม่มีอักขระเหลืออยู่อีกต่อไป การจับคู่จึงล้มเหลว เมื่อไหร่ที่เราสามารถใช้ได้+
? เมื่อเราต้องค้นหารายการที่ตรงกันอย่างน้อยหนึ่งรายการ แต่ไม่สำคัญว่านิพจน์ที่กำหนดจะต้องตรงกันกี่ครั้ง เช่น ถ้าเราต้องการหาตัวเลขที่มีจุดทศนิยม ให้ทำดังนี้
รูปแบบ: \d*\.\d+ สตริง: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 ตรงกัน: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^( ตัวอย่าง ) บันทึกโดยการใส่ตัวเลขทางด้านซ้ายของจุดทศนิยมลงไป เราก็สามารถหาทั้ง 0.011 และ .2 ได้ ในการดำเนินการนี้ เราจำเป็นต้องจับคู่จุดทศนิยมหนึ่งจุดให้ตรงกันกับ
\.
และอย่างน้อยหนึ่งหลักทางด้านขวาของจุดทศนิยม\d+
ด้วย นิพจน์ทั่วไปข้างต้นจะไม่ตรงกับตัวเลขเช่น3.
เนื่องจากเราต้องการอย่างน้อยหนึ่งหลักทางด้านขวาของจุดทศนิยมจึงจะตรงกัน
ตามปกติ เราจะมาแก้ไขปัญหาง่ายๆ สองสามข้อ:
ค้นหาคำภาษาอังกฤษทั้งหมดได้จากข้อความด้านล่างนี้ลวดลาย: สตริง: 3 บวก 3 เป็นหก แต่ 4 บวกสามเป็น 7 ตรงกัน: ^^^^ ^^ ^^^ ^^^ ^^^^ ^^^^^ ^^( วิธีแก้ไข ) ค้นหาสัญลักษณ์ขนาดไฟล์ทั้งหมดในรายการด้านล่าง ขนาดไฟล์จะประกอบด้วยตัวเลข (มีหรือ ไม่มี จุดทศนิยม) ตามด้วย
KB
, MB
หรือGB
:TB
ลวดลาย: สตริง: 11TB 13 14.4MB 22HB 9.9GB TB 0KB ตรงกัน: ^^^^ ^^^^^^ ^^^^^ ^^^( สารละลาย )
ขั้นตอนที่ 9: เครื่องหมายคำถาม "ไม่บังคับ"?

ลวดลาย: สตริง: 1..3KB 5...GB ..6TB การแข่งขัน:แน่นอนว่า การกำหนดเหล่านี้ไม่ใช่ขนาดไฟล์ที่ถูกต้อง ดังนั้นนิพจน์ทั่วไปที่ดีไม่ควรตรงกับขนาดไฟล์อย่างใดอย่างหนึ่ง วิธีแก้ปัญหาที่ฉันเขียนเพื่อแก้ไขปัญหาสุดท้ายนั้นตรงกับทั้งหมด อย่างน้อยก็ในบางส่วน:
รูปแบบ: \d+\.*\d*[KMGT]B สตริง: 1..3KB 5...GB .. 6TB ตรงกัน: ^^^^^^ ^^^^^^ ^^^( ตัวอย่าง ) แล้วปัญหาคืออะไร? ที่จริงแล้ว เราต้องหาจุดทศนิยมเพียงจุดเดียวหากมี แต่
*
อนุญาตให้มีการแข่งขันจำนวนเท่าใดก็ได้ รวมถึงศูนย์ด้วย มีวิธีจับคู่เพียงศูนย์ครั้งหรือครั้งเดียวหรือไม่? แต่ไม่เกินหนึ่งครั้ง? มีแน่นอน. "ทางเลือก" ?
คือตัวปรับแต่งที่จับคู่ศูนย์หรืออักขระตัวใดตัวหนึ่งที่อยู่ข้างหน้า แต่ไม่มากกว่านั้น:
รูปแบบ: \d+\.?\d*[KMGT]B สตริง: 1.. 3KB 5...GB .. 6TB ตรงกัน: ^^^ ^^^( ตัวอย่าง ) เราเข้าใกล้วิธีแก้ปัญหามากขึ้นแล้ว แต่นี่ไม่ใช่สิ่งที่เราต้องการ เราจะดูวิธีแก้ไขปัญหานี้ในไม่กี่ขั้นตอนในภายหลัง
ในระหว่างนี้ เรามาแก้ไขปัญหานี้กัน:
ในภาษาการเขียนโปรแกรมบางภาษา (เช่น Java) ตัวเลขจำนวนเต็มและจำนวนจุดลอยตัว (จุด) บางตัวอาจตามด้วยl
/ L
และf
/ F
เพื่อระบุว่าควรถือเป็นค่า long/float (ตามลำดับ) แทนที่จะเป็น int/double ปกติ ค้นหาตัวเลข "ยาว" ที่ถูกต้องทั้งหมดในบรรทัดด้านล่าง:
ลวดลาย: สาย: 13Lยาว2l 19 L lL 0 นัด: ^^^ ^^ ^^ ^( สารละลาย )
ขั้นตอนที่ 10: เครื่องหมาย "หรือ"|

รูปแบบ: \d*\.\d+ สตริง: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 ตรงกัน: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^รูปแบบด้านบนจะจับคู่ตัวเลขที่มีจุดทศนิยมและมีตัวเลขอย่างน้อยหนึ่งหลักทางด้านขวาของจุดทศนิยม แต่จะเกิดอะไรขึ้นถ้าเราต้องการจับคู่สตริงเช่น
0.
? (ไม่มีตัวเลขทางด้านขวาของจุดทศนิยม) เราสามารถเขียนนิพจน์ทั่วไปได้ดังนี้:
รูปแบบ: \d*\.\d* สตริง: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . ตรงกัน: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^ ^( ตัวอย่าง ) สิ่งนี้ตรงกัน
0.
แต่ยังตรงกับจุดเดียว.
ดังที่คุณเห็นด้านบน จริงๆ แล้วสิ่งที่เราพยายามจับคู่คือคลาสสตริงที่แตกต่างกันสองคลาส:
- ตัวเลขที่มีหลักทางด้านขวาของจุดทศนิยมอย่างน้อยหนึ่งหลัก
- ตัวเลขที่มีจุดทศนิยมทางซ้ายอย่างน้อยหนึ่งหลัก
รูปแบบ: \d*\.\d+ สตริง: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . แมตช์: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^
รูปแบบ: \d+\.\d* สตริง: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . ตรงกัน: ^^^^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^เราเห็นว่าในกรณีเหล่านี้ สตริงย่อย
42
, 5
หรือ6
ไม่.
พบโดยเอ็นจิ้น เพื่อให้ได้ผลลัพธ์ที่ต้องการ การรวมนิพจน์ทั่วไปเหล่านี้เข้าด้วยกันจะไม่เสียหาย เราจะบรรลุเป้าหมายนี้ได้อย่างไร? เครื่องหมาย "หรือ" |
ช่วยให้เราสามารถระบุลำดับการจับคู่ที่เป็นไปได้หลายลำดับพร้อมกันในนิพจน์ทั่วไป เช่นเดียวกับที่[]
เครื่องหมาย "หรือ" ช่วยให้เราสามารถระบุอักขระเดี่ยวทางเลือกได้|
เราก็สามารถระบุนิพจน์ทางเลือกแบบหลายอักขระได้ ตัวอย่างเช่น หากเราต้องการค้นหา "สุนัข" หรือ "แมว" เราสามารถเขียนได้ดังนี้:
รูป แบบ: \w\ w \ w string: แน่นอนสุนัขเป็นสัตว์เลี้ยงที่ดีกว่าแมว ตรงกัน: ^^^^^^^^^ ^^^ ^^^^^^ ^^^ ^^^ ^^^( ตัวอย่าง ) ... แต่สิ่งนี้ตรงกับลำดับอักขระสามตัวทั้งหมดของคลาส "word" แต่ "สุนัข" และ "แมว" ไม่มีตัวอักษรที่เหมือนกันด้วยซ้ำ ดังนั้นวงเล็บเหลี่ยมจึงไม่ช่วยเราในที่นี้ ต่อไปนี้เป็นนิพจน์ทั่วไปที่ง่ายที่สุดที่เราสามารถใช้ได้ซึ่งตรงกับทั้งสองคำนี้เท่านั้น:
รูปแบบ: dog|cat string: แน่นอนว่าสุนัขเป็นสัตว์เลี้ยงที่ดีกว่าแมว ตรงกัน: ^^^ ^^^( ตัวอย่าง ) ขั้นแรกกลไกของนิพจน์ทั่วไปจะพยายามจับคู่ลำดับทั้งหมดทางด้านซ้ายของอักขระ
|
แต่ถ้าไม่สำเร็จ ระบบจะพยายามจับคู่ลำดับทางด้านขวาของ|
อักขระ อักขระหลายตัว|
สามารถเชื่อมโยงกันเพื่อให้ตรงกับลำดับทางเลือกมากกว่าสองลำดับ:
รูป แบบ: dog|cat|pet string: แน่นอนว่าสุนัขเป็นสัตว์เลี้ยง ที่ดี กว่าแมว ตรงกัน: ^^^ ^^^ ^^^( ตัวอย่าง )
ตอนนี้เรามาแก้ไขปัญหาอีกสองสามข้อเพื่อทำความเข้าใจขั้นตอนนี้ให้ดียิ่งขึ้น:
ใช้เครื่องหมาย|
เพื่อแก้ไขนิพจน์ทั่วไปทศนิยมด้านบนเพื่อให้ได้ผลลัพธ์ดังนี้:
ลวดลาย: สตริง: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . ตรงกัน: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^( วิธีแก้ไข ) ใช้เครื่องหมาย คลาส
|
อักขระ "ทางเลือก" ?
ฯลฯ เพื่อสร้างนิพจน์ทั่วไปเดียวที่ตรงกับทั้งจำนวนเต็มและจำนวนจุดลอยตัว (จุด) ตามที่กล่าวไว้ในปัญหาในตอนท้ายของขั้นตอนก่อนหน้า (ปัญหานี้เล็กน้อย) ซับซ้อนกว่านั้นใช่ ;))
ลวดลาย: สาย: 42L 12 x 3.4f 6l 3.3 0F LF .2F 0. ตรงกัน: ^^^ ^^ ^^^^ ^^ ^^^ ^^ ^^^ ^^( วิธีแก้ไข ) 20 ขั้นตอนสั้นๆ เพื่อเชี่ยวชาญนิพจน์ทั่วไป ส่วนที่ 3 RegEx: 20 ขั้นตอนสั้นๆ เพื่อเชี่ยวชาญนิพจน์ทั่วไป ตอนที่ 4
GO TO FULL VERSION