มีคำพูดยอดนิยมโดยJamie Zawinski :
บางคนเมื่อเผชิญกับปัญหาคิดว่า "ฉันรู้ฉันจะใช้สำนวนปกติ" ตอนนี้พวกเขามีสองปัญหา
ควรเข้าใจคำพูดนี้อย่างไร
มีคำพูดยอดนิยมโดยJamie Zawinski :
บางคนเมื่อเผชิญกับปัญหาคิดว่า "ฉันรู้ฉันจะใช้สำนวนปกติ" ตอนนี้พวกเขามีสองปัญหา
ควรเข้าใจคำพูดนี้อย่างไร
คำตอบ:
บางเทคโนโลยีการเขียนโปรแกรมได้โดยทั่วไปดีเข้าใจโดยโปรแกรมเมอร์ ( การแสดงออกปกติ , จุดลอย , Perl , AWK , IoC ... และอื่น ๆ )
สิ่งเหล่านี้สามารถเป็นเครื่องมือที่ทรงพลังอย่างน่าอัศจรรย์สำหรับการแก้ปัญหาที่เหมาะสม การแสดงออกปกติโดยเฉพาะอย่างยิ่งมีประโยชน์มากสำหรับการจับคู่ภาษาปกติ และมีปมปัญหาอยู่: มีคนไม่กี่คนที่รู้วิธีอธิบายภาษาปกติ (เป็นส่วนหนึ่งของทฤษฎีวิทยาการคอมพิวเตอร์ / ภาษาศาสตร์ที่ใช้สัญลักษณ์ตลก - คุณสามารถอ่านเกี่ยวกับเรื่องนี้ในลำดับชั้นของ Chomsky )
เมื่อต้องรับมือกับสิ่งเหล่านี้ถ้าคุณใช้มันผิดมันไม่น่าเป็นไปได้ที่คุณจะแก้ไขปัญหาดั้งเดิมของคุณได้ การใช้นิพจน์ทั่วไปเพื่อจับคู่ HTML (เหตุการณ์ที่เกิดขึ้นบ่อยเกินไป) จะหมายความว่าคุณจะพลาดตัวพิมพ์ของขอบ และตอนนี้คุณยังคงมีปัญหาดั้งเดิมที่คุณไม่ได้แก้ปัญหาและข้อผิดพลาดเล็ก ๆ อีกหนึ่งที่ลอยอยู่รอบ ๆ ซึ่งได้รับการแนะนำโดยใช้วิธีการแก้ปัญหาที่ไม่ถูกต้อง
นี่ไม่ได้เป็นการบอกว่าไม่ควรใช้การแสดงออกปกติ แต่ควรจะใช้เพื่อทำความเข้าใจว่าชุดของปัญหาที่พวกเขาสามารถแก้ไขได้และไม่สามารถแก้ไขและใช้งานได้อย่างรอบคอบ
กุญแจสำคัญในการบำรุงรักษาซอฟต์แวร์คือการเขียนรหัสที่สามารถบำรุงรักษาได้ การใช้นิพจน์ทั่วไปสามารถตอบโต้เป้าหมายนั้นได้ เมื่อทำงานกับนิพจน์ทั่วไปคุณได้เขียนคอมพิวเตอร์ขนาดเล็ก (โดยเฉพาะอย่างยิ่งสถานะ จำกัด อัตโนมัติของคอมพิวเตอร์ ) ในภาษาเฉพาะโดเมน ง่ายต่อการเขียน 'Hello world' ในภาษานี้และได้รับความมั่นใจในพื้นฐาน แต่จะต้องมีความเข้าใจในภาษาปกติมากขึ้นเพื่อหลีกเลี่ยงการเขียนข้อบกพร่องเพิ่มเติมที่ยากที่จะระบุและแก้ไข (เพราะ พวกเขาไม่ได้เป็นส่วนหนึ่งของโปรแกรมที่มีนิพจน์ทั่วไปอยู่)
ดังนั้นตอนนี้คุณมีปัญหาใหม่ คุณเลือกเครื่องมือของการแสดงออกปกติเพื่อแก้ปัญหา (เมื่อมันไม่เหมาะสม) และคุณมีข้อบกพร่องสองข้อในขณะนี้ซึ่งทั้งสองอย่างนั้นยากที่จะหาเพราะพวกมันซ่อนอยู่ในอีกชั้นหนึ่งของสิ่งที่เป็นนามธรรม
นิพจน์ทั่วไป - โดยเฉพาะอย่างยิ่งสิ่งที่ไม่สำคัญ - อาจยากต่อการเข้าใจและบำรุงรักษา คุณเพียงแค่ต้องดูจำนวนคำถามใน Stack Overflow ที่ติดแท็ก[regex]
ที่ผู้ถามได้สันนิษฐานว่าคำตอบสำหรับปัญหาของพวกเขาคือ regex และติดอยู่ในภายหลัง ในหลายกรณีปัญหาสามารถแก้ไขได้ (และควร) ด้วยวิธีอื่น
ซึ่งหมายความว่าหากคุณตัดสินใจใช้ regex ตอนนี้คุณมีปัญหาสองประการ:
โดยพื้นฐานแล้วฉันคิดว่าเขาหมายความว่าคุณควรใช้ regex หากไม่มีวิธีอื่นในการแก้ปัญหาของคุณ โซลูชันอื่นอาจจะง่ายกว่าในการเขียนโค้ดบำรุงรักษาและสนับสนุน อาจช้าลงหรือมีประสิทธิภาพน้อยลง แต่ถ้าหากไม่ใช่เรื่องง่ายในการบำรุงรักษาและการสนับสนุนควรเป็นเรื่องที่น่ากังวล
ส่วนใหญ่มันเป็นเรื่องตลกที่ปากลิ้นแก้มแม้ว่าจะมีเม็ดความจริง
มีงานบางอย่างที่การแสดงผลปกติเหมาะอย่างยิ่ง ฉันเคยแทนที่โค้ดตัวแยกวิเคราะห์โคตร recursive descent ที่เขียนด้วยตนเองด้วยนิพจน์ทั่วไปหนึ่งนิพจน์ซึ่งใช้เวลาประมาณ 10 นาทีในการดีบักอย่างสมบูรณ์ ผู้คนบอกว่า regexes นั้นยากที่จะเข้าใจและตรวจแก้จุดบกพร่อง แต่สิ่งที่ใช้อย่างเหมาะสมนั้นไม่ยากที่จะทำการ debug ในฐานะ parser ที่ออกแบบด้วยมือขนาดใหญ่ ในตัวอย่างของฉันใช้เวลาสองสัปดาห์ในการดีบักเคสขอบทั้งหมดของโซลูชันที่ไม่ใช่ regex
อย่างไรก็ตามการถอดความลุงเบ็น:
ด้วยการแสดงออกที่ดีมาพร้อมความรับผิดชอบที่ดี
กล่าวอีกนัยหนึ่ง regexes เพิ่มความชัดเจนให้กับภาษาของคุณ แต่นั่นทำให้ผู้รับผิดชอบมากขึ้นในการเลือกโหมดการแสดงออกที่อ่านง่ายที่สุดสำหรับงานที่กำหนด
บางสิ่งบางอย่างในตอนแรกดูเหมือนเป็นงานที่ดีสำหรับการแสดงออกปกติ แต่ไม่ได้ ตัวอย่างเช่นสิ่งใดก็ตามที่มีโทเค็นที่ซ้อนกันเช่น HTML บางครั้งคนใช้นิพจน์ทั่วไปเมื่อวิธีที่ง่ายกว่าชัดเจนกว่า ตัวอย่างเช่นstring.endsWith("ing")
เข้าใจง่ายกว่า regex ที่เทียบเท่า บางครั้งผู้คนพยายามยัดเยียดปัญหาใหญ่ให้เป็น regex เดียวโดยที่การแบ่งเป็นชิ้น ๆ มีความเหมาะสมมากกว่า บางครั้งผู้คนล้มเหลวในการสร้าง abstractions ที่เหมาะสมทำซ้ำ regex ซ้ำแล้วซ้ำอีกแทนที่จะสร้างฟังก์ชันที่มีชื่อดีเพื่อทำงานเดียวกัน (อาจนำไปใช้ภายในกับ regex)
ด้วยเหตุผลบางอย่าง regexes มีแนวโน้มแปลก ๆ ที่จะสร้างจุดบอดให้กับหลักการทางวิศวกรรมซอฟต์แวร์ทั่วไปเช่นความรับผิดชอบเดี่ยวและ DRY นั่นเป็นเหตุผลที่แม้แต่คนที่รักพวกเขายังพบปัญหาอยู่ตลอดเวลา
Jeff Atwood นำเสนอการตีความที่แตกต่างออกไปในบล็อกโพสต์ที่พูดถึงสิ่งนี้มาก: นิพจน์ทั่วไป: ตอนนี้คุณมีสองปัญหา (ขอบคุณEuphoricสำหรับลิงค์)
การวิเคราะห์ข้อความทั้งหมดของกระทู้ของเจมี่ในกระทู้ 1997 ต้นฉบับเราพบสิ่งต่อไปนี้:
ธรรมชาติของ Perl ส่งเสริมให้ใช้การแสดงออกปกติเกือบจะยกเว้นเทคนิคอื่น ๆ ทั้งหมด พวกเขาอยู่ไกลและไกลที่สุด "ชัดเจน" (อย่างน้อยที่สุดสำหรับคนที่ไม่รู้จักดี) วิธีที่จะได้รับจากจุด A ถึงจุด B
คำพูดแรกจะกะล่อนเกินไปที่จะดำเนินการอย่างจริงจัง แต่นี่ฉันเห็นด้วยอย่างสมบูรณ์ นี่คือประเด็นที่เจมี่พยายามทำไม่ใช่ว่าการแสดงผลปกติเป็นสิ่งที่ชั่วร้าย แต่สำหรับการแสดงออกปกติมากเกินไปนั้นเป็นสิ่งที่ชั่วร้าย
แม้ว่าคุณจะเข้าใจนิพจน์ทั่วไปอย่างถ่องแท้แล้วก็ตามคุณก็พบปัญหาGolden Hammerพยายามแก้ปัญหาด้วยนิพจน์ทั่วไปเมื่อมันง่ายกว่าและชัดเจนกว่าที่จะทำสิ่งเดียวกันด้วยรหัสปกติ (ดูที่CodingHorror: Regex use เทียบกับการละเมิด Regex )
มีการโพสต์บล็อกอีกอันหนึ่งซึ่งดูที่บริบทของการอ้างถึงและมีรายละเอียดมากกว่า Atwood: บล็อกของ Jeffrey Friedl: ที่มาของชื่อดัง“ ตอนนี้คุณมีปัญหาสองข้อ”
มีบางสิ่งเกิดขึ้นกับคำพูดนี้
อ้างเป็นปรับย้อนหลังของเรื่องตลกก่อนหน้านี้:
เมื่อใดก็ตามที่ประสบปัญหาบางคนพูดว่า "ให้ใช้ AWK" ตอนนี้พวกเขามีสองปัญหา - D. Tilbrook
มันเป็นเรื่องตลกและขุดจริง แต่ก็ยังเป็นวิธีการเน้น regex เป็นวิธีที่ไม่ดีโดยการเชื่อมโยงกับโซลูชั่นที่ไม่ดีอื่น ๆ มันยอดเยี่ยมฮ่าร้ายแรงเพียงสักครู่
สำหรับฉัน - โปรดจำไว้ว่าคำพูดนี้เปิดกว้างสำหรับการตีความ - ความหมายนั้นตรงไปตรงมา เพียงแค่ประกาศความคิดในการใช้นิพจน์ทั่วไปไม่ได้แก้ปัญหา นอกจากนี้คุณได้เพิ่มความซับซ้อนทางปัญญาของรหัสด้วยการเพิ่มภาษาเพิ่มเติมด้วยกฎที่แตกต่างจากภาษาที่คุณใช้
แม้ว่าตลกเป็นเรื่องตลก แต่คุณต้องเปรียบเทียบความซับซ้อนของโซลูชันที่ไม่ใช่ regex กับความซับซ้อนของโซลูชัน regex + ความซับซ้อนเพิ่มเติมของการรวม regexes มันอาจจะคุ้มค่าในการแก้ปัญหากับ regex แม้จะมีค่าใช้จ่ายเพิ่มเติมในการเพิ่ม regexes
RegularExpressionsarenoworsetoreadormaintainthananyotherunformattedcontent; indeedaregexisprobablyeasiertoreadthanthispieceoftexthere-butunfortunatelytheyhaveabadreputationbecausesomeimplementationsdon'tallowformattingandpeopleingeneraldon'tknowthatyoucandoit
(นิพจน์ทั่วไปไม่เลวร้ายกว่าที่จะอ่านหรือดูแลรักษากว่าเนื้อหาที่ไม่ได้จัดรูปแบบอื่น ๆ แน่นอนว่า regex นั้นอาจอ่านได้ง่ายกว่าข้อความชิ้นนี้ที่นี่ - แต่น่าเสียดายที่พวกเขามีชื่อเสียงไม่ดีเพราะการใช้งานบางอย่างไม่อนุญาต ไม่ทราบว่าคุณสามารถทำได้)
นี่เป็นตัวอย่างเล็กน้อย:
^(?:[^,]*+,){21}[^,]*+$
ซึ่งไม่ใช่เรื่องยากที่จะอ่านหรือดูแลรักษา แต่ก็ง่ายกว่าเมื่อดูเช่นนี้:
(?x) # enables comments, so this whole block can be used in a regex.
^ # start of string
(?: # start non-capturing group
[^,]*+ # as many non-commas as possible, but none required
, # a comma
) # end non-capturing group
{21} # 21 of previous entity (i.e. the group)
[^,]*+ # as many non-commas as possible, but none required
$ # end of string
นั่นเป็นตัวอย่างเล็กน้อย (การแสดงความคิดเห็น$
คล้ายกับการแสดงความคิดเห็นi++
) แต่ชัดเจนว่าไม่ควรมีปัญหาในการอ่านทำความเข้าใจและการดูแลรักษา
ตราบใดที่คุณชัดเจนว่าเมื่อใดที่การแสดงออกปกติเหมาะสมและเมื่อพวกเขาเป็นความคิดที่ดีไม่มีอะไรผิดปกติกับพวกเขาและส่วนใหญ่เวลาที่คำพูด JWZ ใช้ไม่ได้จริง ๆ
*+
คืออะไร? มันแตกต่างกันอย่างไร (ตามหน้าที่) จาก*
?
*+
ในกรณีนี้ไม่มีประโยชน์ที่จะทำ ทุกอย่างได้รับการยึดและสามารถจับคู่ในการส่งผ่านครั้งเดียวโดยหุ่นยนต์ที่สามารถนับได้ถึง 22 ตัวดัดแปลงที่ถูกต้องของชุดที่ไม่ใช่จุลภาคนั้นเก่าเพียง*
อย่างเดียว (ยิ่งไปกว่านั้นก็ไม่ควรมีความแตกต่างระหว่างอัลกอริธึมการจับคู่โลภและไม่โลภที่นี่มันเป็นกรณีที่ง่ายมาก)
นอกเหนือจากคำตอบของ ChrisF - การแสดงออกปกติ "นั้นยากที่จะเขียนรหัสทำความเข้าใจและดูแลรักษา" ยิ่งแย่ไปกว่านั้นคือพวกมันมีพลังมากพอที่จะหลอกผู้คนให้ลองใช้มันเพื่อแยกวิเคราะห์สิ่งที่ไม่สามารถทำได้เช่น HTML ดูคำถามมากมายเกี่ยวกับ SO บน "ฉันจะแยก HTML ได้อย่างไร" ยกตัวอย่างเช่นคำตอบเดียวที่ยิ่งใหญ่ที่สุดใน SO!
นิพจน์ทั่วไปนั้นทรงพลังมาก แต่ก็มีปัญหาเล็ก ๆ ปัญหาหนึ่ง เขียนยากและใกล้อ่านไม่ได้
ในกรณีที่ดีที่สุดการใช้นิพจน์ทั่วไปจะช่วยแก้ปัญหาดังนั้นคุณจึงมีปัญหาในการบำรุงรักษาโค้ดที่ซับซ้อนเท่านั้น หากคุณไม่ได้รับนิพจน์ปกติที่ถูกต้องคุณมีทั้งปัญหาดั้งเดิมและปัญหาเกี่ยวกับรหัสที่อ่านไม่ได้ซึ่งใช้งานไม่ได้
บางครั้งนิพจน์ทั่วไปจะเรียกว่ารหัสแบบเขียนอย่างเดียว ต้องเผชิญกับการแสดงออกปกติที่ต้องมีการแก้ไขก็มักจะเริ่มต้นจากศูนย์ได้เร็วกว่าการพยายามที่จะเข้าใจการแสดงออก
ปัญหาคือว่า regex เป็นสัตว์ร้ายที่ซับซ้อนและคุณจะแก้ปัญหาของคุณถ้าคุณใช้ regex อย่างสมบูรณ์ หากไม่เป็นเช่นนั้นคุณจะพบปัญหา 2 ประการ ได้แก่ ปัญหาดั้งเดิมและปัญหา regex
คุณอ้างว่ามันสามารถใช้งานโค้ดได้ร้อยบรรทัด แต่คุณสามารถโต้แย้งได้ว่าโค้ดที่กระชับและชัดเจน 100 บรรทัดนั้นดีกว่า regex หนึ่งบรรทัด
หากคุณต้องการหลักฐานนี้: คุณสามารถตรวจสอบSO Classicนี้หรือเพียงแค่หวีผ่านแท็ก SO Regex
ความหมายมีสองส่วน:
ตามที่คุณถามในปี 2014 มันจะน่าสนใจที่จะมุ่งเน้นไปที่แนวคิดการเขียนโปรแกรมภาษาของบริบทปี 1997 เมื่อเทียบกับบริบทของวันนี้ ฉันจะไม่ป้อนการอภิปรายนี้ที่นี่ แต่ความคิดเห็นเกี่ยวกับ Perl และ Perl เองมีการเปลี่ยนแปลงอย่างมาก
แต่จะอยู่ในบริบทที่ 2013 ( de l'eau coulé sous les Ponts Depuis) ผมจะแนะนำให้ความสำคัญกับแนคท์ในเครื่องหมายคำพูดโดยใช้การ์ตูน XKCD ที่มีชื่อเสียงที่เป็นใบเสนอราคาโดยตรงของเจมี่ซาวินสกีหนึ่ง :
ก่อนอื่นฉันมีปัญหาในการเข้าใจการ์ตูนเรื่องนี้เพราะมันเป็นการอ้างอิงถึงคำพูดของ Zawinski และคำพูดของเนื้อเพลง Jay-z และการอ้างอิงของ GNU program --help -z
flag 2ดังนั้นมันจึงเป็นวัฒนธรรมที่มากเกินไปสำหรับฉันที่จะเข้าใจ
ฉันรู้ว่ามันสนุกฉันรู้สึกมัน แต่ฉันไม่รู้จริงๆว่าทำไม คนมักจะทำเรื่องตลกเกี่ยวกับ Perl และ regexes โดยเฉพาะอย่างยิ่งตั้งแต่ยังไม่การเขียนโปรแกรมภาษา hipstiest ไม่ทราบจริงๆว่าทำไมมันควรจะเป็นความสนุกสนาน ... อาจจะเป็นเพราะแม่ค้า Perl ทำสิ่งโง่
ดังนั้นคำพูดเริ่มต้นดูเหมือนจะเป็นเรื่องตลกประชดประชันบนพื้นฐานของปัญหาในชีวิตจริง (ความเจ็บปวด?) ที่เกิดจากการเขียนโปรแกรมด้วยเครื่องมือที่เจ็บ เช่นเดียวกับค้อนสามารถทำร้ายช่างก่อสร้างได้การเขียนโปรแกรมด้วยเครื่องมือที่ไม่ใช่สิ่งที่นักพัฒนาซอฟต์แวร์จะเลือกถ้าเขาสามารถทำร้ายได้ (สมองความรู้สึก) บางครั้งการอภิปรายที่ดีเกี่ยวกับเครื่องมือที่ดีที่สุดที่เกิดขึ้น แต่ก็เกือบจะไร้ค่าสาเหตุมันเป็นปัญหาของรสนิยมของคุณหรือรสชาติทีมงานเขียนโปรแกรมของคุณ , วัฒนธรรมหรือเศรษฐกิจเหตุผล อีกหนึ่งการ์ตูน XKCD ที่ยอดเยี่ยมเกี่ยวกับเรื่องนี้:
ฉันสามารถเข้าใจผู้คนที่รู้สึกเจ็บปวดเกี่ยวกับ regexes และพวกเขาเชื่อว่าเครื่องมืออื่นเหมาะกว่าสำหรับสิ่งที่ออกแบบมาสำหรับ regexes @ @ karl-bielefeldt ตอบคำถามของคุณด้วยการแสดงออกที่ดีมาพร้อมความรับผิดชอบที่ดีและ regexes มีความกังวลโดยเฉพาะอย่างยิ่งนี้ หากนักพัฒนาไม่สนใจว่า s-เขาจะจัดการกับ regexes ในที่สุดมันจะเป็นความเจ็บปวดสำหรับคนที่จะรักษารหัสในภายหลัง
ฉันจะจบด้วยคำตอบนี้เกี่ยวกับการยืนยันคำพูดโดยการเสนอราคาที่แสดงตัวอย่างทั่วไปจากDamian Conw ay Perl Best Practices (หนังสือปี 2005)
เขาอธิบายว่าการเขียนรูปแบบเช่นนี้:
m{'[^\\']*(?:\\.[^\\']*)*'}
... ไม่ยอมรับมากกว่าการเขียนโปรแกรมเช่นนี้ :
sub'x{local$_=pop;sub'_{$_>=$_[0
]?$_[1]:$"}_(1,'*')._(5,'-')._(4
,'*').$/._(6,'|').($_>9?'X':$_>8
?'/':$")._(8,'|').$/._(2,'*')._(
7,'-')._(3,'*').$/}print$/x($=).
x(10)x(++$x/10).x($x%10)while<>;
แต่มันสามารถเขียนใหม่ได้มันยังไม่สวย แต่อย่างน้อยตอนนี้ก็สามารถเอาตัวรอดได้
# Match a single-quoted string efficiently...
m{ ' # an opening single quote
[^\\']* # any non-special chars (i.e., not backslash or single quote)
(?: # then all of...`
\\ . # any explicitly backslashed char
[^\\']* # followed by any non-special chars
)* # ...repeated zero or more times
' # a closing single quote
}x
รหัสรูปสี่เหลี่ยมชนิดนี้เป็นปัญหาที่สองที่ไม่ใช่ regexes ที่สามารถจัดรูปแบบได้อย่างชัดเจนบำรุงรักษาและอ่านได้
/* Multiply the first 10 values in an array by 2. */ for (int i = 0 /* the loop counter */; i < 10 /* continue while it is less than 10 */; ++i /* and increment it by 1 in each iteration */) { array[i] *= 2; /* double the i-th element in the array */ }
หากมีสิ่งหนึ่งที่คุณควรเรียนรู้จากวิทยาการคอมพิวเตอร์มันเป็นลำดับชั้นของชัม ฉันจะบอกว่าปัญหาทั้งหมดเกี่ยวกับการแสดงออกปกติมาจากความพยายามในการแยกไวยากรณ์ที่ไม่มีบริบท เมื่อคุณสามารถกำหนดขีด จำกัด (หรือคิดว่าคุณสามารถกำหนดวงเงิน) เพื่อทำรังในระดับ CFG คุณจะได้รับนิพจน์ปกติที่ซับซ้อนและยาว
นิพจน์ทั่วไปเหมาะสมกว่าสำหรับการทำโทเค็นมากกว่าการแยกวิเคราะห์แบบเต็ม
แต่สิ่งที่มีขนาดใหญ่อย่างน่าประหลาดใจที่โปรแกรมเมอร์ต้องแยกวิเคราะห์นั้นใช้ภาษาปกติ (หรือแย่กว่านั้นคือเกือบจะแยกเป็นภาษาปกติและถ้าคุณเขียนโค้ดเพิ่มอีกนิดหน่อย ... )
ดังนั้นหากมีตัวเคย "aha ฉันต้องเลือกข้อความแยกกันฉันจะใช้นิพจน์ปกติ" มันง่ายที่จะลงเส้นทางนั้นเมื่อคุณต้องการบางสิ่งที่ใกล้กับออโตเมติกแบบกดลง CFG parser หรือ ไวยากรณ์ที่มีประสิทธิภาพยิ่งขึ้น มันมักจะจบลงด้วยน้ำตา
ดังนั้นฉันคิดว่าการเสนอราคาไม่ใช่ regexps ที่กระแทกอย่างรุนแรงพวกเขามีการใช้งาน (และใช้งานได้ดีมีประโยชน์มากจริง ๆ ) แต่การพึ่งพา regexps มากเกินไป (หรือโดยเฉพาะอย่างยิ่งการเลือกที่ไม่สำคัญของพวกเขา) .
jwz เป็นเพียงแค่โยกออกของเขาด้วยคำพูดที่ การแสดงออกปกติไม่แตกต่างจากคุณสมบัติของภาษาใด ๆ - ง่ายต่อการทำให้ตกใจยากที่จะใช้อย่างหรูหรามีประสิทธิภาพในเวลาที่ไม่เหมาะสมในบางครั้งเอกสารที่ดีมักจะมีประโยชน์
อาจกล่าวได้ว่าเป็นเลขทศนิยม, การปิด, การวางแนววัตถุ, I / O แบบอะซิงโครนัสหรืออะไรก็ได้ที่คุณสามารถตั้งชื่อได้ หากคุณไม่รู้ว่ากำลังทำอะไรภาษาการเขียนโปรแกรมสามารถทำให้คุณเศร้า
หากคุณคิดว่า regexes อ่านยากลองอ่านการใช้ parser ที่เทียบเท่าเพื่อใช้รูปแบบที่เป็นปัญหา มักจะ regexes ชนะเพราะพวกเขามีขนาดกะทัดรัดกว่า parsers เต็ม ... และในภาษาส่วนใหญ่พวกเขาจะเร็วขึ้นเช่นกัน
ไม่ต้องออกจากการใช้การแสดงออกปกติ (หรือคุณสมบัติภาษาอื่น ๆ ) เพราะบล็อกเกอร์ที่ส่งเสริมตัวเองทำให้งบไม่เหมาะสม ลองด้วยตัวคุณเองและดูว่าอะไรเหมาะกับคุณ
คำตอบเชิงลึกที่ชื่นชอบสำหรับเรื่องนี้ได้รับจาก Rob Pike ที่มีชื่อเสียงในโพสต์บล็อกทำซ้ำจากความคิดเห็นรหัสภายในของ Google: http://commandcenter.blogspot.ch/2011/08/regular-expressions-in-lexing- and.html
สรุปก็คือไม่ใช่ว่าพวกเขาจะไม่ดีแต่พวกเขามักจะใช้สำหรับงานที่พวกเขาไม่เหมาะสมโดยเฉพาะอย่างยิ่งเมื่อมันมาถึง lexing และแยกวิเคราะห์บางส่วน
นิพจน์ทั่วไปนั้นยากที่จะเขียนยากที่จะเขียนได้ดีและอาจมีราคาแพงเมื่อเทียบกับเทคโนโลยีอื่น ๆ ... Lexers ในทางกลับกันค่อนข้างง่ายต่อการเขียนอย่างถูกต้อง (ถ้าไม่ใช่ขนาดกะทัดรัด) และง่ายต่อการทดสอบ ลองค้นหาตัวระบุและตัวเลข มันไม่ยากเกินไปที่จะเขียน regexp (บางอย่างเช่น "[a-ZA-Z _] [a-ZA-Z_0-9] *") แต่ก็ไม่ยากที่จะเขียนเป็นวงแบบง่ายๆ แม้ว่าประสิทธิภาพของลูปจะสูงขึ้นมากและจะเกี่ยวข้องกับรหัสน้อยลงภายใต้การครอบคลุม ห้องสมุดการแสดงออกปกติเป็นเรื่องใหญ่ การใช้ตัวระบุคำสั่งแยกวิเคราะห์ก็เหมือนกับการใช้ Ferrari เพื่อไปที่ร้านขายนม
เขาบอกว่ามากกว่านั้นการโต้แย้งว่านิพจน์ทั่วไปนั้นมีประโยชน์เช่นการจับคู่รูปแบบที่ใช้แล้วทิ้งในเครื่องมือแก้ไขข้อความ แต่ไม่ค่อยควรใช้ในโค้ดที่คอมไพล์แล้ว มันคุ้มค่าที่จะอ่าน
สิ่งนี้เกี่ยวข้องกับ epigram ของ Alan Perlis # 34:
สตริงเป็นโครงสร้างข้อมูลที่สมบูรณ์และทุกที่ที่ส่งผ่านจะมีการทำซ้ำมาก มันเป็นยานพาหนะที่สมบูรณ์แบบสำหรับการซ่อนข้อมูล
ดังนั้นหากคุณเลือกสตริงอักขระเป็นโครงสร้างข้อมูลของคุณ (และตามปกติโค้ดที่ใช้ regex เป็นอัลกอริทึมในการจัดการ) คุณมีปัญหาแม้ว่าจะใช้งานได้: การออกแบบที่ไม่ดีรอบ ๆ การแสดงข้อมูลที่ไม่เหมาะสม ขยายและไม่มีประสิทธิภาพ
อย่างไรก็ตามบ่อยครั้งมันใช้งานไม่ได้: ปัญหาดั้งเดิมไม่ได้รับการแก้ไขดังนั้นในกรณีนี้คุณมีปัญหาสองประการ
Regexes ใช้กันอย่างแพร่หลายสำหรับการแยกวิเคราะห์ข้อความที่รวดเร็วและสกปรก พวกเขาเป็นเครื่องมือที่ยอดเยี่ยมสำหรับแสดงรูปแบบที่ซับซ้อนเล็กน้อยกว่าเพียงแค่การจับคู่สตริงธรรมดา
อย่างไรก็ตามเมื่อ regexes พบปัญหาเซิร์ฟเวอร์ที่ซับซ้อนมากขึ้น
ดังนั้นจึงเป็นเรื่องง่ายเกินไปที่จะเริ่มต้นด้วยปัญหาการประมวลผลข้อความใช้นิพจน์ทั่วไปกับมันและจบลงด้วยปัญหาสองปัญหาเดิมที่คุณพยายามแก้ไขและจัดการกับนิพจน์ทั่วไปที่พยายามแก้ไข (แต่การแก้ไม่ถูกต้อง) ปัญหาเดิม