นิพจน์ทั่วไปคืออะไร
นิพจน์ทั่วไปหรือที่เรียกว่า regex ทำงานโดยกำหนดรูปแบบที่คุณสามารถใช้ค้นหาอักขระหรือคำบางตัวภายในสตริงได้
เมื่อคุณกำหนดรูปแบบที่คุณต้องการใช้แล้ว คุณสามารถทำการแก้ไข ลบอักขระหรือคำบางตัว แทนที่สิ่งหนึ่งด้วยสิ่งอื่น แยกข้อมูลที่เกี่ยวข้องจากไฟล์หรือสตริงใดๆ ที่มีรูปแบบเฉพาะนั้น และอื่นๆ
เหตุใดคุณจึงควรเรียนรู้ Regex
Regex ช่วยให้คุณสามารถประมวลผลข้อความในลักษณะที่ช่วยให้คุณประหยัดเวลาได้มาก นอกจากนี้ยังสามารถนำเสนอความสนุกสนานในกระบวนการได้อีกด้วย
การใช้ regex ช่วยให้ค้นหาข้อมูลได้ง่ายขึ้นมาก เมื่อคุณพบเป้าหมายแล้ว คุณสามารถแก้ไข/ทำซ้ำ/ลบเป็นชุด หรือการประมวลผลใดๆ ก็ตามที่คุณต้องทำ
ตัวอย่างการใช้งานจริงบางส่วนของการใช้ regex คือการเปลี่ยนชื่อไฟล์เป็นแบตช์ การแยกวิเคราะห์บันทึก การตรวจสอบความถูกต้องของแบบฟอร์ม การแก้ไขจำนวนมากในโค้ดเบส และการค้นหาแบบเรียกซ้ำ
ในบทช่วยสอนนี้ เราจะพูดถึงพื้นฐานของ regex ด้วยความช่วยเหลือจากไซต์นี้ หลังจากนั้น ฉันจะแนะนำความท้าทายเกี่ยวกับ regex ที่คุณจะแก้ไขโดยใช้ Python ฉันจะแสดงให้คุณเห็นถึงวิธีการใช้เครื่องมือเช่น 01 และ 16รหัส> ด้วย regex.
เช่นเดียวกับหลายๆ สิ่งในชีวิต การแสดงออกเป็นประจำเป็นหนึ่งในสิ่งที่คุณจะเข้าใจได้อย่างแท้จริงโดยการทำเท่านั้น ฉันขอแนะนำให้คุณลองใช้ regex ขณะที่คุณกำลังอ่านบทความนี้
สารบัญ
- พื้นฐาน Regex
- ตรงทั้งหมด
- ชุดอักขระ
- จับคู่ช่วงใน regex
- จับคู่อักขระที่ไม่อยู่ในชุด
- คลาสตัวละคร
- ปริมาณ
- จับภาพกลุ่ม
- วิธีใช้ตรรกะ OR ใน regex
- วิธีอ้างอิงกลุ่มการจับ
- วิธีตั้งชื่อกลุ่มการบันทึก
- วิธีใช้ regex ด้วยเครื่องมือบรรทัดคำสั่ง
- การค้นหา regex แบบเรียกซ้ำด้วย grep
- การทดแทนด้วย sed
- Regex ขั้นสูง:การค้นหา
- มองไปด้านหลัง
- การมองไปข้างหน้า
- ตัวอย่างการใช้งานจริงของ Regex
- การแยกวิเคราะห์บันทึก
- การเปลี่ยนชื่อไฟล์จำนวนมาก
- การตรวจสอบอีเมล
- ข้อจำกัดของรหัสผ่าน
- คำพูดสุดท้าย
พื้นฐาน Regex
นิพจน์ทั่วไปไม่ใช่อะไรนอกจากลำดับของอักขระที่ตรงกับรูปแบบ นอกจากการใช้อักขระตัวอักษร (เช่น 'abc') แล้ว ยังมีอักขระเมตาบางตัว (*,+,? และอื่นๆ) ซึ่งมีวัตถุประสงค์พิเศษ นอกจากนี้ยังมีฟีเจอร์ต่างๆ เช่น คลาสอักขระซึ่งสามารถช่วยให้คุณลดความซับซ้อนของนิพจน์ทั่วไปได้ ป>
ก่อนที่จะเขียน regex คุณจะต้องเรียนรู้เกี่ยวกับกรณีพื้นฐานและกรณีขอบทั้งหมดสำหรับรูปแบบที่คุณกำลังมองหา ป>
ตัวอย่างเช่น หากคุณต้องการจับคู่ 'Hello World' คุณต้องการให้บรรทัดขึ้นต้นด้วย 'Hello' หรือขึ้นต้นด้วยอะไรก็ได้ คุณต้องการช่องว่างระหว่าง 'Hello' และ 'World' เพียงหนึ่งช่องหรืออาจมีมากกว่านั้นก็ได้ ตัวละครอื่นสามารถมาหลัง 'World' ได้หรือควรจบบรรทัดตรงนั้น? คุณสนใจเกี่ยวกับความละเอียดอ่อนของตัวพิมพ์เล็กและใหญ่หรือไม่? และอื่นๆ
คำถามเหล่านี้เป็นคำถามที่คุณต้องมีคำตอบก่อนจะนั่งเขียน regex
ตรงทั้งหมด
รูปแบบพื้นฐานที่สุดของ regex คือการจับคู่ลำดับอักขระในลักษณะเดียวกับที่คุณสามารถทำได้ด้วย Ctrl-F ในโปรแกรมแก้ไขข้อความ
ที่ด้านบน คุณจะเห็นจำนวนรายการที่ตรงกัน และที่ด้านล่างมีคำอธิบายว่า regex จับคู่อะไรกับอักขระทีละอักขระ
ชุดอักขระ
ชุดอักขระ Regex ช่วยให้คุณสามารถจับคู่อักขระตัวใดก็ได้จากกลุ่มอักขระ กลุ่มนี้ล้อมรอบด้วยวงเล็บเหลี่ยม [] ป>
ตัวอย่างเช่น 20 จับคู่ "ไท" และ "ธี" ที่นี่ 't' และ 'i' ได้รับการแก้ไขแล้ว แต่ระหว่างทั้งสองสามารถมี 'a' หรือ 'h' ได้
จับคู่ช่วงใน regex
บางครั้งคุณอาจต้องการจับคู่กลุ่มอักขระที่มีลักษณะตามลำดับ เช่น ตัวอักษรภาษาอังกฤษตัวพิมพ์ใหญ่ แต่การเขียนจดหมายทั้ง 26 ฉบับคงจะค่อนข้างน่าเบื่อ ป>
Regex แก้ไขปัญหานี้ด้วยช่วง "-" ทำหน้าที่เป็นตัวดำเนินการช่วง ช่วงที่ถูกต้องบางช่วงแสดงอยู่ด้านล่าง:
RangeMatches [A-Z]ตัวอักษรพิมพ์ใหญ่[a-z]ตัวอักษรพิมพ์เล็ก[0-9]ตัวเลขใดๆ
คุณยังสามารถระบุช่วงบางส่วนได้ เช่น 33 เพื่อจับคู่ตัวอักษร 'bcde' หรือ 45 ใดก็ได้ เพื่อให้ตรงกับตัวเลข '3456' ใดๆ
คุณไม่ได้จำกัดเพียงการระบุช่วงเดียวภายในชุดอักขระ คุณสามารถใช้หลายช่วงและรวมเข้ากับอักขระเพิ่มเติมอื่นๆ ได้ ที่นี่ 52 จะจับคู่ค่าใดก็ได้ของ '3456uvw' หรืออัฒภาค ';'
จับคู่อักขระที่ไม่อยู่ในชุด
หากคุณนำหน้าชุดด้วย '^' การดำเนินการผกผันจะดำเนินการ ตัวอย่างเช่น 65 จะจับคู่อะไรก็ได้ยกเว้นตัวอักษรตัวพิมพ์ใหญ่และตัวเลข
คลาสตัวละคร
ขณะเขียน regex คุณจะต้องจับคู่กลุ่มบางกลุ่ม เช่น ตัวเลขค่อนข้างบ่อยและหลายครั้งในนิพจน์เดียวกันด้วย ป>
ตัวอย่างเช่น คุณจะจับคู่รูปแบบเช่น 'letter-digit-letter-digit' อย่างไร ป>
จากสิ่งที่คุณได้เรียนรู้มาจนถึงตอนนี้ คุณสามารถสร้าง 72 ได้ . วิธีนี้ใช้ได้ผล แต่คุณจะเห็นได้ว่านิพจน์จะยุ่งได้อย่างไรเมื่อความยาวของรูปแบบใหญ่ขึ้น
เพื่อให้นิพจน์ง่ายขึ้น คลาสจึงถูกกำหนดให้กับกลุ่มอักขระที่มีการกำหนดไว้อย่างดี เช่น ตัวเลข ตารางต่อไปนี้แสดงคลาสเหล่านี้และนิพจน์ที่เทียบเท่ากับชุดอักขระ:
ClassMatchesEquivalent expression .อะไรก็ได้ยกเว้น newline[^\n\r]\wword character[a-zA-Z0-9_]\Wnon-word character[^\w]\ddigits[0-9]\Dnon-digits[^\d]\sspace, tab, newlines[ \t\r\n\f]\Snon whitespace character[^\s]คลาสตัวละครมีประโยชน์มากและทำให้สำนวนของคุณสะอาดขึ้นมาก เราจะใช้พวกมันอย่างกว้างขวางตลอดบทช่วยสอนนี้ ดังนั้นคุณสามารถใช้ตารางนี้เป็นจุดอ้างอิงและกลับมาที่นี่หากคุณลืมคลาสใดคลาสหนึ่ง
โดยส่วนใหญ่ เราจะไม่สนใจตำแหน่งทั้งหมดในรูปแบบ "." class ช่วยเราจากการเขียนอักขระที่เป็นไปได้ทั้งหมดในชุด ป>
ตัวอย่างเช่น 83 จับคู่อะไรก็ได้ที่ขึ้นต้นด้วย t และอักขระสองตัวใดๆ ในภายหลัง นี่อาจทำให้คุณนึกถึง SQL 98 โอเปอเรเตอร์ซึ่งจะใช้ 106 เพื่อทำสิ่งเดียวกันให้สำเร็จ
ปริมาณ
คำว่า "รูปแบบ" และ "การทำซ้ำ" เป็นของคู่กัน หากคุณต้องการจับคู่ตัวเลข 3 หลัก คุณสามารถใช้ 115 . แต่ถ้าคุณต้องการจับคู่ตัวเลข 11 หลักล่ะ? คุณสามารถเขียน '\d' ได้ 11 ครั้ง แต่หลักทั่วไปในขณะที่เขียน regex หรือแค่เขียนโปรแกรมใดๆ ก็คือ หากคุณพบว่าตัวเองทำอะไรซ้ำๆ มากกว่าสองครั้ง คุณอาจไม่ทราบถึงคุณสมบัติบางอย่าง ป>
ใน regex คุณสามารถใช้ตัวระบุเพื่อจุดประสงค์นี้ได้ หากต้องการจับคู่ตัวเลข 11 หลัก คุณสามารถเขียนนิพจน์ 124 ได้ .
ตารางด้านล่างแสดงรายการปริมาณที่คุณใช้ได้ใน regex:
การจับคู่ปริมาณ *0 หรือมากกว่า?0 หรือ 1+1 หรือมากกว่า{n}อย่างแน่นอน n ครั้ง{n, }n หรือมากกว่านั้น{n, m}รวม n ถึง m เท่า
ในตัวอย่างนี้ นิพจน์ 138 ตรงกับ 147 ตามด้วยช่องว่าง 1 ช่องขึ้นไป ตามด้วย 152 . แต่คุณจะเห็นได้ว่า 'canwrite' ไม่ตรงกับ 166 หมายความว่าต้องมีการจับคู่ช่องว่างอย่างน้อยหนึ่งช่อง สิ่งนี้มีประโยชน์เมื่อคุณค้นหาผ่านข้อความที่ไม่ได้ถูกตัดออก
คุณเดาได้ไหมว่า 171 จะตรงกันไหม?
จับภาพกลุ่ม
กลุ่มการจับภาพคือนิพจน์ย่อยที่อยู่ในวงเล็บ () คุณสามารถมีกลุ่มการจับจำนวนเท่าใดก็ได้ และแม้แต่กลุ่มการจับที่ซ้อนกัน
นิพจน์ 182 ตรงกับ 'The' สองครั้ง แต่ไม่มีแคปเจอร์กรุ๊ป นิพจน์ 191 จะจับคู่ 'The' ตามด้วยช่องว่าง 2 ช่อง เนื่องจากตัวปริมาณจะถูกนำไปใช้กับอักขระช่องว่าง และจะไม่ใช้กับ 'The ' เป็นกลุ่ม
คุณสามารถจับคู่รูปแบบภายในกลุ่มการจับได้เช่นเดียวกับที่คุณทำกับ regex ที่ถูกต้อง ที่นี่ 203 จับคู่หากพบว่า 'is' ตามด้วยช่องว่าง 1 ช่องขึ้นไปสองครั้ง
วิธีใช้ตรรกะ OR ใน regex
คุณสามารถใช้ "|" เพื่อให้เข้ากับหลายรูปแบบ 214รหัส> จับคู่ 'นี่คือ ' ตามด้วย 'ดี' หรือ 'ไม่ดี' หรือ 'หวาน' ใดๆ
คุณต้องเข้าใจถึงความสำคัญของกลุ่มผู้ลักลอบที่นี่อีกครั้ง ลองนึกถึงนิพจน์ 227 จะตรงกันไหม?
ด้วยกลุ่มแคปเจอร์ 231 แยกได้จาก 241 . แต่หากไม่ได้อยู่ในกลุ่มแคปเจอร์ regex ทั้งหมดก็เป็นเพียงกลุ่มเดียวเท่านั้น ดังนั้นนิพจน์ 253 จะจับคู่หากสตริงมี 'สิ่งนี้ดี' หรือ 'ไม่ดี' หรือ 'หวาน'
วิธีอ้างอิงกลุ่มการจับ
กลุ่มการจับภาพสามารถอ้างอิงได้ในนิพจน์เดียวกันหรือในขณะที่ดำเนินการแทนที่ดังที่คุณเห็นในแท็บการแทนที่ ป>
เครื่องมือและภาษาส่วนใหญ่อนุญาตให้คุณอ้างอิงกลุ่มที่บันทึกไว้กลุ่มที่ n ด้วย '\n' ในเว็บไซต์นี้ '$n' ถูกใช้เพื่ออ้างอิงถึงการเปลี่ยน ไวยากรณ์สำหรับการแทนที่จะแตกต่างกันไปขึ้นอยู่กับเครื่องมือหรือภาษาที่คุณใช้ ตัวอย่างเช่น สำหรับ JavaScript จะใช้ '$n' ส่วน Python จะใช้ '\n'
ในนิพจน์ 265 , 'This' ถูกจับแล้วอ้างอิงด้วย '\1' ซึ่งตรงกับ 274 อย่างมีประสิทธิภาพ .
วิธีตั้งชื่อกลุ่มการบันทึก
คุณสามารถตั้งชื่อกลุ่มแคปเจอร์ของคุณด้วยไวยากรณ์ 289 และอ้างอิงกลับด้วยนิพจน์เดียวกันกับ 292 . ป>
ในการเปลี่ยน การอ้างอิงทำได้โดย 306 . นี่คือไวยากรณ์สำหรับ JavaScript และอาจแตกต่างกันไปตามภาษา คุณสามารถเรียนรู้เกี่ยวกับความแตกต่างได้ที่นี่ โปรดทราบว่าคุณลักษณะนี้อาจไม่สามารถใช้ได้ในบางภาษา
ในนิพจน์ 310 รูปแบบ 324 ถูกจับด้วยชื่อ 'lang' และอ้างอิงกลับด้วย 332 . รูปแบบนี้จะจับคู่อักขระคำใดๆ หรืออักขระ '+' 1 ครั้งขึ้นไป 340รหัส> ที่ส่วนท้ายของ regex จะจับคู่อักขระใดๆ 0 หรือมากกว่าครั้ง และสุดท้ายในการแทนที่ การอ้างอิงจะกระทำโดย 357 .
มีเครื่องมือ CLI ดีๆ ที่ให้คุณดำเนินการ regex จากเทอร์มินัลของคุณได้ เครื่องมือเหล่านี้ช่วยให้คุณประหยัดเวลาได้มากขึ้น เนื่องจากคุณสามารถทดสอบ regex ต่างๆ ได้อย่างง่ายดายโดยไม่ต้องเขียนโค้ดเป็นภาษาใดภาษาหนึ่ง จากนั้นจึงคอมไพล์หรือตีความมัน ป>
เครื่องมือที่รู้จักกันดีบางส่วน ได้แก่ grep, sed และ awk ลองดูตัวอย่างเล็กๆ น้อยๆ เพื่อให้แนวคิดเกี่ยวกับวิธีการใช้ประโยชน์จากเครื่องมือเหล่านี้
การค้นหา regex แบบเรียกซ้ำด้วย grep
คุณสามารถดำเนินการพลังของ regex ผ่าน grep Grep สามารถค้นหารูปแบบในไฟล์หรือทำการค้นหาแบบเรียกซ้ำได้
หากคุณใช้ Windows คุณสามารถติดตั้ง grep โดยใช้ winget รันคำสั่งนี้ใน PowerShell:
winget install -e --id GnuWin32.Grep
ฉันจะแสดงวิธีแก้ปัญหาให้กับความท้าทายที่ฉันสร้างขึ้นสำหรับการแข่งขัน CTF ที่มหาวิทยาลัยของฉัน ป>
ไฟล์ที่แนบมากับภารกิจนี้เป็นไฟล์ ZIP ที่มีไดเร็กทอรีหลายระดับและมีไฟล์จำนวนมากอยู่ในนั้น ชื่อการแข่งขันคือ Coderush รูปแบบธง 368 . ดังนั้นคุณต้องค้นหารูปแบบ 378 ซึ่งจะตรงกับรูปแบบธง 388 .
แตกไฟล์ด้วย 399 และ cd เข้าไปด้วย 406 .
มี 358 ไดเร็กทอรีและ 8731 ไฟล์ แทนที่จะค้นหารูปแบบในไฟล์ทีละไฟล์ คุณสามารถใช้ grep ได้ดังนี้:
grep --color -R "coderush{.*}"
ธง "-R" ช่วยให้สามารถค้นหาแบบเรียกซ้ำได้
คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ grep และตัวเลือกบรรทัดคำสั่งได้ที่นี่
การแทนที่ด้วย sed
คุณสามารถใช้ sed เพื่อแทรก ลบ แทนที่ไฟล์ข้อความได้โดยการระบุ regex หากคุณใช้ windows คุณสามารถรับ sed ได้จากที่นี่ หรือหากคุณใช้ WSL เครื่องมืออย่าง grep และ sed ก็จะพร้อมใช้งานอยู่แล้ว
นี่คือการใช้งาน sed ที่พบบ่อยที่สุด:
sed 's/pattern/replacement/g' filename
echo "${text}" | sed 's/pattern/replacement/g'
ในที่นี้ มีการระบุตัวเลือก "g" เพื่อแทนที่เหตุการณ์ทั้งหมด
ตัวเลือกที่มีประโยชน์อื่นๆ คือ 415 เพื่อระงับพฤติกรรมเริ่มต้นของการพิมพ์ทุกบรรทัดและใช้ p แทน g เพื่อพิมพ์เฉพาะบรรทัดที่ได้รับผลกระทบจาก regex
มาดูเนื้อหาของ texts.txt กันดีกว่า
Hello rand chars World 56 rand chars
Henlo 52 rand chars W0rld rand chars
GREP rand chars Henlo 62 rand chars
Henlo 10 rand chars Henlo rand chars
GREP rand chars Henlo 45 rand chars
งานของเราคือการแทนที่ 426 ด้วย 432 เฉพาะในบรรทัดที่มี "GREP" เท่านั้น ดังนั้นเราจึงค้นหารูปแบบ 445 ซึ่งจะจับคู่ 'Henlo' ตามด้วยตัวเลข 1 ตัวขึ้นไป และจะจับตัวเลขทั้งหมด จากนั้นสตริงแทนที่ของเราจะเป็น 454 – '\1' อ้างอิงถึงกลุ่มการจับที่มีตัวเลข
วิธีหนึ่งในการบรรลุผลสำเร็จคือการใช้ grep เพื่อ grep บรรทัดที่มี "GREP" อยู่ จากนั้นทำการแทนที่ด้วย sed
grep "GREP" texts.txt | sed -En 's/Henlo ([0-9]+)/Hello \1/p'
ตัวเลือก "-E" เปิดใช้งาน regex แบบขยายโดยที่คุณไม่ต้องหลีกวงเล็บ
หรือคุณสามารถใช้ sed ใช้ 467 เพื่อจำกัดการแทนที่เฉพาะบรรทัดที่มีรูปแบบอยู่
sed -En '/GREP/ s/Henlo ([0-9]+)/Hello \1/p' texts.txt
Regex ขั้นสูง:การค้นหา
Lookaheads และ Lookbehinds (เรียกรวมกันว่า lookarounds) เป็นฟีเจอร์ของ regex ที่ให้คุณตรวจสอบการมีอยู่ของรูปแบบโดยไม่ต้องรวมไว้ในการจับคู่
คุณสามารถคิดว่าสิ่งเหล่านี้เป็นการยืนยันความกว้างเป็นศูนย์ โดยยืนยันการมีอยู่ของรูปแบบ แต่ไม่ใช้อักขระใดๆ ในการแข่งขัน นี่เป็นคุณสมบัติที่ทรงพลังมาก แต่ก็มีราคาแพงในการคำนวณเช่นกัน ดังนั้นอย่าลืมติดตามประสิทธิภาพหากคุณใช้งานบ่อยๆ
มองไปข้างหลัง
สมมติว่าคุณต้องการจับคู่คำว่า 'linux' แต่คุณมี 2 เงื่อนไข
- คำว่า 'GNU' ต้องเกิดขึ้นก่อนที่ 'linux' จะเกิดขึ้น หากบรรทัดมี 'linux' แต่ไม่มี 'GNU' ก่อนหน้า เราต้องการละทิ้งบรรทัดนั้น
- เราต้องการจับคู่เฉพาะ
478และไม่มีอะไรอื่น
เรารู้วิธีปฏิบัติตามเงื่อนไขที่ 1 แล้ว 489รหัส> จะจับคู่ 'GNU' ตามด้วยอักขระจำนวนเท่าใดก็ได้ ในที่สุดเราก็จับคู่คำว่า 497 . ซึ่งจะตรงกับ 502 ทั้งหมด .
แต่เราจะป้องกันการจับคู่ 515 ได้อย่างไร ในขณะที่ยังคงรักษาสภาวะที่ 1 เอาไว้?
นั่นคือที่มาของการมองข้างหลังเชิงบวก คุณสามารถทำเครื่องหมายกลุ่มจับภาพเป็นการมองข้างหลังเชิงบวกโดยนำหน้าด้วย 523 . ในตัวอย่างนี้ นิพจน์จะกลายเป็น 530 .
ตอนนี้เพียง 547 ตรงกันและไม่มีอะไรอื่น
โปรดทราบว่านิพจน์ 557 และ 561 จะมีพฤติกรรมเหมือนกันทุกประการ ในนิพจน์ที่ 2 แม้ว่า 577 ก่อนมองหลังจะมี 588 หลัง 'GNU' ซึ่งตรงกับ 590 . ซึ่งหมายความว่ามันตอบสนองการมองข้างหลัง ป>
เพื่อให้ง่ายขึ้น ให้คิดถึงรูปแบบโดยไม่ต้องมองข้างหลัง รูปแบบ 602 จะจับคู่ 'GNU' และอะไรก็ตามหลังจากนั้น ในกรณีของเราตรงกับ 616 .
ตอนนี้เราสามารถได้รับคำสั่งทั่วไปว่านิพจน์ 629 จะตรงกับรูปแบบ X – เฉพาะในกรณีที่รูปแบบ C มาก่อน X (และต้องไม่รวม C ในการแข่งขัน)
คุณยังสามารถกลับเงื่อนไขที่ 1 ได้อีกด้วย จับคู่บรรทัดที่มีคำว่า 636 เฉพาะในกรณีที่ 644 ไม่เคยมาก่อนหน้านั้น นี่เรียกว่าการมองข้างหลังในแง่ลบ คำนำหน้าในกรณีนี้คือ 659 . ค่าผกผันของนิพจน์ก่อนหน้าจะเป็น 663 .
การมองไปข้างหน้า
Lookaheads ยังเป็นการยืนยันเหมือนกับ lookbehinds ดังที่คุณเห็นในตัวอย่างก่อนหน้านี้ ข้อแตกต่างเพียงอย่างเดียวคือผู้มองหลังจะยืนยันก่อน และคนมองข้างหน้าจะยืนยันทีหลัง
สมมติว่าคุณมีเงื่อนไขสองข้อนี้:
- จับคู่
673เฉพาะในกรณีที่689มาที่ไหนสักแห่งหลังจากนั้น - จับคู่เฉพาะ Hello เท่านั้น ไม่มีอะไรอื่น
คำนำหน้าสำหรับ lookahead เชิงบวกคือ 695 . นิพจน์ 708 จะได้ครบทั้งสองเงื่อนไข ซึ่งคล้ายกับ 716 ยกเว้นเพียง 726 จะถูกจับคู่ในขณะที่ 731 จะจับคู่ 'Hello', 'World' และอะไรก็ได้ที่อยู่ระหว่างนั้น
คล้ายกับตัวอย่างในการมองด้านหลังเชิงบวก นิพจน์ 746 และ 759 เทียบเท่ากัน เนื่องจาก 767 ก่อนที่ 'World' จะตรงกับ 771 เป็นไปตามเงื่อนไขที่ 1
การมองไปข้างหน้าเชิงลบเป็นเพียงส่วนเสริมของการมองไปข้างหน้าเชิงลบ คุณสามารถใช้ได้โดยนำหน้าด้วย 780 . 795รหัส> จะตรงกับ 809 เฉพาะในกรณีที่ไม่มี 814 ที่ไหนก็ได้หลังจากนั้น
นี่คือบทสรุปของไวยากรณ์สำหรับการค้นหาเมื่อคุณต้องการจับคู่รูปแบบ X กับการยืนยัน C
OperationRegEx มองไปข้างหน้าเชิงบวก822 มองไปข้างหน้าเชิงลบ831 มองไปทางบวก844 มองไปทางลบ857 การแยกวิเคราะห์บันทึก
ในไฟล์บันทึกนี้ บรรทัดเหล่านี้คือบรรทัดที่เราสนใจ:
[1/10000] Train loss: 11.30368, Valid loss: 8.95446, Elapsed_time: 7.58941
[500/10000] Train loss: 0.96180, Valid loss: 0.20098, Elapsed_time: 82.48651
[1000/10000] Train loss: 0.04051, Valid loss: 0.11927, Elapsed_time: 156.86243
หน้าที่ของเราคือการแยกการสูญเสียการฝึกอบรมและการสูญเสียการตรวจสอบเพื่อวัตถุประสงค์ เช่น การวางแผนการสูญเสียในยุคต่างๆ เราจำเป็นต้องแยกค่าการสูญเสียการฝึก เช่น 860 และวางไว้ในอาร์เรย์
ค่าที่เกี่ยวข้องทั้งหมดขึ้นต้นด้วย '874 ' เพื่อให้เราสามารถใช้สิ่งนี้ใน regex ของเราได้เหมือนเดิม เพื่อให้ตรงกับตัวเลขทศนิยม เราต้องจับคู่ตัวเลขบางหลักตามด้วย "882 " แล้วตามด้วยหลักเพิ่มเติม คุณสามารถทำได้ด้วย 893 . เนื่องจากเราต้องการติดตามตัวเลขเหล่านี้ จึงควรอยู่ในกลุ่มดักจับ
เป็น "." มีวัตถุประสงค์พิเศษใน regex เมื่อคุณต้องการจับคู่ "." ตัวละครที่คุณต้องหลีกหนีด้วยแบ็กสแลช สิ่งนี้ใช้ได้กับตัวละครทุกตัวที่มีวัตถุประสงค์พิเศษ แต่คุณไม่จำเป็นต้องหลีกเลี่ยงมันภายในชุดอักขระ
โดยรวมแล้ว สำนวนสำหรับการแยกการสูญเสียการฝึกคือ 908 . เราสามารถใช้ตรรกะเดียวกันเพื่อแยกการสูญเสียการตรวจสอบความถูกต้องด้วย 917 .
นี่เป็นวิธีหนึ่งในการดึงข้อมูลนี้โดยใช้ Python:
import re
f = open("log_train.txt", "r").read()
train_loss = re.findall(r'Train loss: (\d+\.\d+)', f)
valid_loss = re.findall(r'Valid loss: (\d+\.\d+)', f)
train_loss = [float(i) for i in train_loss]
valid_loss = [float(i) for i in valid_loss]
print("train_loss =", train_loss)
print("")
print("valid_loss =", valid_loss)
เมื่อมีกลุ่มแคปเจอร์หนึ่งกลุ่ม 923 ค้นหาทุกบรรทัดและส่งกลับค่าภายในกลุ่มการจับในรายการ ป>
ฟังก์ชัน regex ใดๆ จะส่งคืนสตริงเท่านั้น ดังนั้นค่าจะถูกแปลงเป็นแบบทศนิยมและพิมพ์ออกมา จากนั้นคุณสามารถใช้พวกมันในสคริปต์ Python อื่นเป็นรายการโฟลตได้โดยตรง
นี่คือผลลัพธ์:
คุณยังสามารถใช้ sed บันทึกเอาต์พุตใน train_losses.txt และอ่านจากไฟล์ได้ อันดับแรก เราใช้ '/Train/' เพื่อกำหนดเป้าหมายเฉพาะบรรทัดที่มี 'Train' ปรากฏ จากนั้นเราจะใช้ regex เหมือนเดิม
sed -En '/Train/ s/.*Train loss: ([0-9]+\.[0-9]+).*/\1/p' log_train.txt | tee train_losses.txt
".*" ถูกเพิ่มที่จุดเริ่มต้นและจุดสิ้นสุดเพื่อให้ sed ตรงกับเนื้อหาของบรรทัดที่เกี่ยวข้องทั้งหมด จากนั้นทั้งบรรทัดจะถูกแทนที่ด้วยค่าของกลุ่มแคปเจอร์ 933รหัส> คำสั่งใช้เพื่อเปลี่ยนเส้นทางเอาต์พุตของ sed ไปยัง train_losses.txt ในขณะเดียวกันก็พิมพ์เนื้อหาในเทอร์มินัลด้วย
ใช้เวลาสักครู่เพื่อคิดถึงสิ่งที่คุณต้องการเพื่อดึงเอายุคสมัยต่างๆ ออกมา คุณต้องแยก 500 จาก [500/10000] สำหรับบรรทัดดังกล่าวทั้งหมด อาร์เรย์ควรมีลักษณะดังนี้ [1, 500, 1,000, 1500, ...] คุณสามารถปฏิบัติตามแนวทางเดียวกันกับที่เราใช้สำหรับตัวอย่างก่อนหน้านี้ ป>
โปรดทราบว่าหากคุณต้องการจับคู่ "949 " หรือ "953 "คุณต้องหนีมัน คำตอบมีให้ที่นี่
การเปลี่ยนชื่อไฟล์จำนวนมาก
คุณมีไฟล์เหล่านี้โดยมีค่าสุ่มเป็นคำนำหน้า คุณต้องเปลี่ยนชื่อไฟล์ทั้งหมดเป็น 1.mp4, 2.mp4 และอื่นๆ นี่คือวิธีการสร้างไฟล์
นี่เป็นสถานการณ์ทั่วไปที่คุณมีรายการไฟล์ที่มีหมายเลขลำดับอยู่ในชื่อ แต่ก็มีอักขระอื่นที่คุณไม่ต้องการด้วย
รูปแบบจะต้องตรงกับอะไรก็ตามจนถึงตอนที่ จากนั้นตามด้วยขีดล่าง ตามด้วยตัวเลข และ .mp4 ต่อท้าย ป>
ค่าที่เกี่ยวข้องคือตัวเลขก่อน '.mp4' ซึ่งเราจะใส่ไว้ในกลุ่มแคปเจอร์
ดังนั้น regex สุดท้ายคือ
นี่เป็นวิธีหนึ่งในการแก้ปัญหาโดยใช้ sed
ขั้นแรก ชื่อใหม่จะถูกบันทึกในตัวแปร จากนั้นคำสั่ง mv จะใช้ในการเปลี่ยนชื่อไฟล์
เราสามารถใช้
จะเกิดอะไรขึ้นหากไฟล์บางไฟล์ตั้งชื่อเป็น "Random_Episode6.mp4"? ความแตกต่างคือไม่มีขีดล่างหลัง Episode คุณจะต้องทำการเปลี่ยนแปลงอะไรบ้าง
คำตอบคือคุณจะต้องเพิ่ม "?" หลัง "_" เพื่อให้เป็นทางเลือก regex จะเป็น
มี Regex ที่ซับซ้อนทุกประเภทสำหรับการตรวจสอบอีเมล
ต่อไปนี้เป็นวิธีง่ายๆ:
ตารางด้านล่างแบ่งรูปแบบนี้ออกเป็นส่วนเล็กๆ:
ในไซต์ regexr คุณสามารถเปิดใช้งานแฟล็กหลายบรรทัดได้จากแท็บแฟล็กที่มุมขวาบน เครื่องหมาย 'gm' ต่อท้ายแสดงว่าเปิดใช้งานแฟล็กหลายบรรทัดแล้ว
เราจะเห็นว่าบรรทัดที่ 2,3,5,6 ไม่ตรงกัน คุณสามารถหาสาเหตุและส่วนใดของ regex ที่รับผิดชอบในการตัดสิทธิ์ได้หรือไม่
คำตอบมีให้ที่นี่
คุณยังสามารถใช้ regex เพื่อกำหนดข้อจำกัดได้ ที่นี่เราจะค้นพบพลังของการมองไปข้างหน้าเชิงบวก ป>
สมมติว่าเราต้องการยอมรับสตริงก็ต่อเมื่อมีตัวเลขอยู่ในนั้น คุณรู้วิธีค้นหาตัวเลขด้วยคลาส '\d' แล้ว เพื่อให้บรรลุเป้าหมายดังกล่าว เราสามารถใช้
เรายังสามารถใช้นิพจน์
เมื่อเราใช้ภาษาการเขียนโปรแกรม เราสามารถตรวจสอบว่า regex ส่งคืนสตริงว่างหรือไม่ และพิจารณาว่าไม่เป็นไปตามข้อจำกัด
เราจะสร้าง regex ซึ่งกำหนดเกณฑ์ต่อไปนี้:
เพื่อให้บรรลุเป้าหมายนี้ คุณสามารถใช้การมองล่วงหน้าเชิงบวกได้ นี่คือ regex:
ตารางด้านล่างจะอธิบายว่าส่วนใดของ regex ที่กำหนดข้อจำกัดใด:
คุณต้องมีการปรับเปลี่ยนอะไรบ้างในการกำหนดอักษรตัวพิมพ์ใหญ่อย่างน้อย 5 ตัว
คุณอาจคิดว่า
อีกครั้งที่เรามีกลุ่มจับกุมมาช่วยเหลือ เราต้องการจับคู่อักษรตัวพิมพ์ใหญ่ 5 ตัวที่ใดก็ได้ในสตริง เรารู้อยู่แล้วว่าเราสามารถจับคู่อักษรตัวพิมพ์ใหญ่ 1 ตัวกับ
นี่คือคำตอบสุดท้าย:
แทนที่
คุณยังอาจกำหนดให้รหัสผ่านไม่มีคำบางคำเพื่อบังคับใช้รหัสผ่านที่รัดกุมยิ่งขึ้น ป>
ตัวอย่างเช่น เราต้องการปฏิเสธรหัสผ่านหากมี
ใน regex นี้ เราใส่
ฉันหวังว่าคุณจะได้รับการฝึกฝนที่ดีในขณะที่อ่านบทความนี้ ไม่เป็นไรถ้าคุณลืมไวยากรณ์บางอย่าง สิ่งสำคัญคือการทำความเข้าใจแนวคิดหลักและมีความคิดที่ดีเกี่ยวกับสิ่งที่เป็นไปได้ใน regex จากนั้น หากคุณลืมรูปแบบ คุณก็แค่ค้นหาใน Google หรืออ้างอิงสูตรโกงก็ได้ ป>
ยิ่งคุณฝึกฝนมากเท่าไร คุณก็ยิ่งได้รับความช่วยเหลือมากขึ้นเท่านั้นโดยไม่ได้รับความช่วยเหลือจากภายนอก ในที่สุดคุณจะสามารถเขียน regex ที่ซับซ้อนและมีประสิทธิภาพแบบออฟไลน์ได้อย่างสมบูรณ์ ป>
มีสูตรโกง regex ดีๆ อยู่แล้วอยู่แล้ว ดังนั้นฉันจึงต้องการสร้างสิ่งที่เจาะลึกกว่านี้ที่นี่เพื่อให้คุณใช้อ้างอิงสำหรับแนวคิดหลักและกรณีการใช้งานทั่วไปได้ ป>
หากคุณกำลังมองหาสูตรโกง เอกสารจาก QuickRef ก็มีประโยชน์ เป็นสถานที่ที่ดีในการจำไวยากรณ์และยังให้ภาพรวมพื้นฐานของฟังก์ชันที่เกี่ยวข้องกับ regex ในภาษาการเขียนโปรแกรมต่างๆ
เทคนิค regex ส่วนใหญ่เหมือนกันในทุกภาษาการเขียนโปรแกรมและเครื่องมือ แต่เครื่องมือบางอย่างอาจมีคุณสมบัติเพิ่มเติม ดังนั้นให้ค้นคว้าเกี่ยวกับเครื่องมือที่คุณใช้เพื่อเลือกเครื่องมือที่ดีที่สุดสำหรับคุณ
คำแนะนำสุดท้ายของฉันคืออย่าบังคับให้ใช้ regex เพียงเพราะคุณทำได้ หลายครั้งที่
หากคุณชอบบทความประเภทนี้ คุณสามารถติดตามบล็อกหรือ Twitter ของฉันได้
เรียนรู้การเขียนโค้ดฟรี หลักสูตรโอเพ่นซอร์สของ freeCodeCamp ช่วยให้ผู้คนมากกว่า 40,000 คนได้งานในตำแหน่งนักพัฒนา เริ่มต้น 964รหัส> จะจับคู่ทุกอย่างให้ตรงตามจำนวน จากนั้นเราก็สามารถจับหมายเลขด้วย 976 และจับคู่ .mp4 กับ 984 . ป> 990 . ตามที่เราต้องการเก็บ 1001 ไว้ สตริงการแทนที่จะเป็น 1012 .for i in *.mp4; do
newname=$(echo $i | sed -En 's/.*Episode_([0-9]+)\.mp4/\1.mp4/p')
mv $i $newname
done;ls
1021 ได้ไหม แทนที่ 1032 ? ในตัวอย่างนี้ ใช่ แต่อาจมีชื่อไฟล์เช่น 1047 โดยที่ 1058 เป็นส่วนหนึ่งของชื่อภาพยนตร์ และคุณไม่ต้องการเปลี่ยนชื่อไฟล์นี้จริงๆ ดังนั้น ควรระบุให้เฉพาะเจาะจงมากที่สุดเสมอจะดีกว่า1069 .การตรวจสอบอีเมล
1075 . ซึ่งตรงกับรูปแบบ 1088 ป> 1098รหัส> จุดเริ่มต้นของบรรทัด1101 อะไรก็ได้ยกเว้น "@" และอักขระเว้นวรรค1111 @ ตามด้วยอะไรก็ได้ ยกเว้น "@" และ "." อักขระ 1122 "." ตามด้วยอักขระคำ1130 สิ้นสุดบรรทัด ข้อจำกัดของรหัสผ่าน
1145 . ซึ่งจะจับคู่อักขระที่ไม่ใช่ตัวเลข 0 ครั้งขึ้นไป จากนั้นจึงจับคู่ตัวเลข ป> 1158 ได้ด้วย เพื่อให้ตรงกับตัวเลขหนึ่งหลัก ดังนั้นหากไม่มีตัวเลขในสตริง lookahead จะล้มเหลว และไม่มีอักขระใดในสตริงนั้นที่จะจับคู่ โดยส่งคืนสตริงว่าง "" ป>
1167รหัส> ป> 1174รหัส> ขั้นต่ำ 8 และสูงสุด 16 ตัวอักษร1180 อักษรตัวพิมพ์เล็กอย่างน้อยหนึ่งตัว1190 อักษรตัวพิมพ์ใหญ่อย่างน้อยหนึ่งตัว1204 ขั้นต่ำหนึ่งหลัก 1210 จะทำงาน แต่สำนวนนี้ต้องการให้ตัวอักษรทั้ง 5 ตัวอยู่รวมกัน สตริงเช่น 1221 จะตรงกันแต่ 1233 จะไม่ตรงกันแม้ว่าจะมีอักษรตัวพิมพ์ใหญ่ 5 ตัว (เนื่องจากไม่ได้อยู่ติดกัน)1243 ได้ . ตอนนี้เราจะใส่พวกมันไว้ในกลุ่มแคปเจอร์และแนบตัวปริมาณขั้นต่ำ 5 นิพจน์จะเป็น 1250 .1262 คุณจะต้องมี 1277 . นิพจน์จะกลายเป็น 1287 .1292 หรือ 1304รหัส> . การมองล่วงหน้าเชิงลบเป็นเครื่องมือสำหรับงานนี้ regex จะเป็น 1316 .1322 และ 1335รหัส> ภายในกลุ่มการจับภาพและใช้ตัวดำเนินการเชิงตรรกะหรือ กลุ่มการจับนี้ซ้อนอยู่ในกลุ่มการจับอื่นซึ่งขึ้นต้นด้วย 1341 . ซึ่งทำให้เป็น lookahead เชิงลบที่จับคู่หากมีอักขระอย่างน้อย 8 ตัวภายใน 1356 โดยมีเงื่อนไขว่า 1360 หรือ 1375 ไม่สามารถปรากฏได้ทุกที่ในสตริงคำสุดท้าย
1380 ปกติ ก็เพียงพอที่จะทำงานให้สำเร็จได้ แต่ถ้าคุณอาศัยอยู่ในเทอร์มินัล คุณสามารถทำอะไรได้มากมายด้วย regex แน่นอน