มุมมองทางประวัติศาสตร์
บทความ Wikipediaค่อนข้างละเอียดเกี่ยวกับต้นกำเนิดของนิพจน์ทั่วไป (Kleene, 1956) ไวยากรณ์เดิมค่อนข้างง่ายมีเพียง*, +, ?, และการจัดกลุ่ม| (...)มันสั้น ( และสามารถอ่านได้ทั้งสองไม่จำเป็นต้องคัดค้าน) เพราะภาษาทางการมักจะแสดงด้วยสัญกรณ์คณิตศาสตร์สั้น ๆ
ต่อมาไวยากรณ์และความสามารถในการพัฒนากับบรรณาธิการและขึ้นอยู่กับPerlซึ่งได้รับการพยายามที่จะรวบรัดโดยการออกแบบ ( "การก่อสร้างทั่วไปควรจะสั้น" ) สิ่งนี้ทำให้ไวยากรณ์ซับซ้อนขึ้นมาก แต่โปรดทราบว่าขณะนี้ผู้คนคุ้นเคยกับการแสดงออกปกติและสามารถเขียนได้ดี (ถ้าไม่อ่าน) ความจริงที่ว่าบางครั้งพวกเขาเขียนเท่านั้นแนะนำว่าเมื่อพวกเขายาวเกินไปพวกเขามักจะไม่ใช่เครื่องมือที่เหมาะสม
นิพจน์ทั่วไปมักไม่สามารถอ่านได้เมื่อถูกทารุณกรรม
เกินกว่าการแสดงออกปกติตามสตริง
พูดเกี่ยวกับไวยากรณ์ทางเลือกลองดูที่มีอยู่แล้ว ( cl-ppcreในCommon LISP ) นิพจน์ทั่วไปที่ยาวของคุณสามารถแยกวิเคราะห์ได้ppcre:parse-stringดังนี้:
(let ((*print-case* :downcase)
      (*print-right-margin* 50))
  (pprint
   (ppcre:parse-string "^(?:([A-Za-z]+):)?(\\/{0,3})(0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$")))
... และผลลัพธ์ในรูปแบบต่อไปนี้:
(:sequence :start-anchor
 (:greedy-repetition 0 1
  (:group
   (:sequence
    (:register
     (:greedy-repetition 1 nil
      (:char-class (:range #\A #\Z)
       (:range #\a #\z))))
    #\:)))
 (:register (:greedy-repetition 0 3 #\/))
 (:register
  (:sequence "0-9" :everything "-A-Za-z"
   (:greedy-repetition 1 nil #\])))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\:
    (:register
     (:greedy-repetition 1 nil :digit-class)))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\/
    (:register
     (:greedy-repetition 0 nil
      (:inverted-char-class #\? #\#))))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\?
    (:register
     (:greedy-repetition 0 nil
      (:inverted-char-class #\#))))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\#
    (:register
     (:greedy-repetition 0 nil :everything)))))
 :end-anchor)
ไวยากรณ์นี้เป็น verbose มากขึ้นและถ้าคุณดูความคิดเห็นด้านล่างไม่จำเป็นต้องอ่านเพิ่มเติม จึงไม่คิดว่าเพราะคุณมีไวยากรณ์ที่มีขนาดกะทัดรัดน้อยกว่าสิ่งที่จะชัดเจนโดยอัตโนมัติ
อย่างไรก็ตามหากคุณเริ่มมีปัญหากับนิพจน์ทั่วไปการเปลี่ยนเป็นรูปแบบนี้อาจช่วยให้คุณถอดรหัสและตรวจแก้รหัสของคุณได้ นี่เป็นข้อดีอย่างหนึ่งของรูปแบบสตริงที่ข้อผิดพลาดของอักขระเดียวสามารถมองเห็นได้ยาก
ประโยชน์หลักของไวยากรณ์นี้คือการจัดการกับนิพจน์ทั่วไปโดยใช้รูปแบบที่มีโครงสร้างแทนการเข้ารหัสแบบสตริง ที่ช่วยให้คุณสามารถเขียนและสร้างนิพจน์เช่นโครงสร้างข้อมูลอื่น ๆ ในโปรแกรมของคุณ เมื่อฉันใช้ไวยากรณ์ข้างต้นนี้เป็นเพราะฉันต้องการสร้างการแสดงออกจากส่วนเล็ก ๆ (ดูคำตอบ CodeGolf ของฉัน ) สำหรับตัวอย่างของคุณเราอาจเขียน1 :
`(:sequence
   :start-anchor
   ,(protocol)
   ,(slashes)
   ,(domain)
   ,(top-level-domain) ... )
นอกจากนี้ยังสามารถสร้างนิพจน์ทั่วไปที่ใช้สตริงได้โดยใช้การต่อสตริงและหรือการแก้ไขในฟังก์ชันตัวช่วย แต่มีข้อ จำกัด ที่มีกิจวัตรสตริงซึ่งมีแนวโน้มที่จะถ่วงรหัส (คิดว่าเกี่ยวกับปัญหาการทำรังไม่แตกต่างจาก backticks เทียบกับ$(...)ในทุบตี; ยังหลบหนีตัวละครอาจทำให้คุณปวดหัว)
โปรดทราบว่าแบบฟอร์มด้านบนอนุญาตให้ใช้(:regex "string")แบบฟอร์มเพื่อให้คุณสามารถผสมเครื่องหมายคำย่อกับต้นไม้ ทั้งหมดนี้นำไปสู่ IMHO ในการอ่านและเรียงความที่ดี มันระบุถึงปัญหาสามข้อที่แสดงโดย delnanทางอ้อม (กล่าวคือไม่ได้อยู่ในภาษาของการแสดงออกปกติ)
สรุป
เพื่อจุดประสงค์ส่วนใหญ่สัญกรณ์สั้น ๆ ในความเป็นจริงสามารถอ่านได้ มีปัญหาเมื่อต้องรับมือกับความหมายที่เพิ่มขึ้นซึ่งเกี่ยวข้องกับการย้อนรอย ฯลฯ แต่การใช้ของพวกเขานั้นไม่ค่อยเป็นธรรม การใช้นิพจน์ทั่วไปที่ไม่มีการรับประกันสามารถนำไปสู่นิพจน์ที่ไม่สามารถอ่านได้
 
นิพจน์ทั่วไปไม่จำเป็นต้องเข้ารหัสเป็นสตริง หากคุณมีไลบรารีหรือเครื่องมือที่สามารถช่วยคุณสร้างและเขียนนิพจน์ทั่วไปคุณจะหลีกเลี่ยงข้อบกพร่องที่อาจเกิดขึ้นมากมายที่เกี่ยวข้องกับการจัดการสตริง
 
อีกทางเลือกหนึ่งไวยากรณ์แบบเป็นทางการสามารถอ่านได้มากขึ้นและดีกว่าในการตั้งชื่อและสรุปย่อยการแสดงออก โดยทั่วไปเทอร์มินัลจะแสดงเป็นนิพจน์ทั่วไปอย่างง่าย
 
1.คุณอาจต้องการสร้างนิพจน์ของคุณในเวลาอ่านเนื่องจากนิพจน์ทั่วไปมักจะเป็นค่าคงที่ในแอปพลิเคชัน ดูcreate-scannerและload-time-value:
'(:sequence :start-anchor #.(protocol) #.(slashes) ... )