นิพจน์ทั่วไป
แสดงออกปกติ (สั้นลงเป็นregexหรือregexp ; [1]นอกจากนี้ยังเรียกว่าการแสดงออกที่มีเหตุผล[2] [3] ) เป็นลำดับของตัวอักษรที่ระบุการค้นหารูปแบบ โดยปกติรูปแบบดังกล่าวจะใช้โดยอัลกอริทึมการค้นหาสตริงสำหรับการดำเนินการ "ค้นหา" หรือ "ค้นหาและแทนที่" บนสตริงหรือสำหรับการตรวจสอบความถูกต้องของอินพุต เป็นเทคนิคที่พัฒนาขึ้นในวิทยาศาสตร์คอมพิวเตอร์เชิงทฤษฎีและทฤษฎีภาษาที่เป็นทางการ

(? < = \ .) {2,} (? = [AZ] )


แนวคิดนี้เกิดขึ้นในช่วงทศวรรษที่ 1950 เมื่อสตีเฟนโคลคลีนนักคณิตศาสตร์ชาวอเมริกันกำหนดคำอธิบายภาษาปกติอย่างเป็นทางการ แนวคิดนี้ถูกนำมาใช้ร่วมกับยูทิลิตี้การประมวลผลข้อความUnix ไวยากรณ์ที่แตกต่างกันสำหรับการเขียนนิพจน์ทั่วไปมีมาตั้งแต่ทศวรรษที่ 1980 หนึ่งเป็นมาตรฐานPOSIXและอีกแบบหนึ่งที่ใช้กันอย่างแพร่หลายคือไวยากรณ์Perl
การแสดงออกปกติจะใช้ในเครื่องมือค้นหา , ค้นหาและแทนที่กล่องโต้ตอบของโปรแกรมประมวลผลคำและแก้ไขข้อความในข้อความการประมวลผลระบบสาธารณูปโภคเช่นsedและAWKและวิเคราะห์คำศัพท์ ภาษาโปรแกรมจำนวนมากมีความสามารถในการ regex ทั้งในตัวหรือผ่านไลบรารีเนื่องจากมีการใช้งานในหลายสถานการณ์
รูปแบบ
วลีที่แสดงออกปกติหรือregexesมักใช้ในความหมายที่เฉพาะเจาะจงเกี่ยวกับใจไวยากรณ์มาตรฐานสำหรับการเป็นตัวแทนของรูปแบบสำหรับข้อความที่ตรงกันแตกต่างไปจากสัญกรณ์คณิตศาสตร์อธิบายไว้ด้านล่าง อักขระแต่ละตัวในนิพจน์ทั่วไป (นั่นคืออักขระแต่ละตัวในสตริงที่อธิบายรูปแบบของมัน) อาจเป็นอักขระเมตาที่มีความหมายพิเศษหรืออักขระทั่วไปที่มีความหมายตามตัวอักษร ตัวอย่างเช่นใน regex b.
"b" คืออักขระตามตัวอักษรที่ตรงกับ "b" ในขณะที่ " เป็นอักขระเมตาที่ตรงกับอักขระทุกตัวยกเว้นขึ้นบรรทัดใหม่ ดังนั้น regex นี้จึงจับคู่เช่น "b%" หรือ "bx" หรือ "b5" สามารถใช้อักขระเมตาและอักขระตามตัวอักษรร่วมกันเพื่อระบุข้อความของรูปแบบที่กำหนดหรือประมวลผลอินสแตนซ์จำนวนมากได้ การจับคู่รูปแบบอาจแตกต่างกันไปตั้งแต่ความเท่าเทียมกันอย่างแม่นยำไปจนถึงความคล้ายคลึงกันโดยทั่วไปตามที่ควบคุมโดยอักขระเมตา ตัวอย่างเช่น.
เป็นรูปแบบทั่วไปมาก[a-z]
(จับคู่ตัวอักษรตัวพิมพ์เล็กทั้งหมดจาก 'a' ถึง 'z') มีความกว้างน้อยกว่าและb
เป็นรูปแบบที่แม่นยำ (จับคู่แค่ 'b') ไวยากรณ์ metacharacter ถูกออกแบบมาเพื่อเป็นตัวแทนของเป้าหมายที่กำหนดไว้ในที่กระชับและวิธีการที่ยืดหยุ่นเพื่อนำระบบอัตโนมัติของการประมวลผลข้อความของความหลากหลายของการป้อนข้อมูลในรูปแบบง่ายต่อการพิมพ์โดยใช้มาตรฐานASCII แป้นพิมพ์
กรณีที่ง่ายมากของนิพจน์ทั่วไปในไวยากรณ์นี้คือการค้นหาคำที่สะกดสองวิธีที่แตกต่างกันในโปรแกรมแก้ไขข้อความโดยนิพจน์ทั่วไปจะseriali[sz]e
จับคู่ทั้ง "serialise" และ "serialize" อักขระไวลด์การ์ดก็ทำได้เช่นกัน แต่มีข้อ จำกัด มากกว่าในรูปแบบที่สามารถทำได้เนื่องจากมีอักขระเมตาคาร์ดน้อยลงและมีพื้นฐานภาษาที่เรียบง่าย
บริบทปกติของอักขระตัวแทนอยู่ในglobbingชื่อที่คล้ายกันในรายชื่อของไฟล์ในขณะที่ regexes มักจะมีการจ้างงานในการใช้งานที่สตริงข้อความรูปแบบการแข่งขันในทั่วไป ตัวอย่างเช่น regex จะจับคู่ช่องว่างส่วนเกินที่จุดเริ่มต้นหรือจุดสิ้นสุดของบรรทัด การแสดงออกปกติขั้นสูงที่ตรงกับเลขใด ๆ ที่เป็น^[ \t]+|[ \t]+$
[+-]?(\d+(\.\d+)?|\.\d+)([eE][+-]?\d+)?

( sวิธี * "ศูนย์หรือมากกว่าของ s ")
ประมวลผล regexแปลนิพจน์ปกติในไวยากรณ์ข้างต้นเป็นตัวแทนภายในที่สามารถดำเนินการและจับคู่กับสตริงตัวแทนเป็นข้อความค้นหาใน. วิธีการหนึ่งที่เป็นไปได้คือขั้นตอนวิธีการก่อสร้าง ธ อมป์สันที่จะสร้างหุ่นยนต์ จำกัด nondeterministic (NFA) ซึ่ง จากนั้นจะถูกกำหนดให้เป็นแบบดีเทอร์มินิสติกและผลลัพธ์ที่ได้จากการกำหนดอัตโนมัติ จำกัด (DFA) จะถูกรันบนสตริงข้อความเป้าหมายเพื่อรับรู้สตริงย่อยที่ตรงกับนิพจน์ทั่วไป ภาพแสดงโครงร่าง NFA ที่ได้รับจากนิพจน์ทั่วไปโดยที่sหมายถึงนิพจน์ทั่วไปที่ง่ายกว่าซึ่งได้รับการแปลซ้ำเป็น NFA N ( s ) แล้วN(s*)
s*
ประวัติศาสตร์
การแสดงออกปกติเกิดขึ้นในปี 1951 เมื่อนักคณิตศาสตร์สตีเฟนโคลคลีนอธิบายภาษาปกติโดยใช้สัญกรณ์คณิตศาสตร์ของเขาที่เรียกว่าเหตุการณ์ที่เกิดขึ้นเป็นประจำ [4] [5]เหล่านี้เกิดขึ้นในวิชาวิทยาการคอมพิวเตอร์ในฟิลด์ของทฤษฎีออโต (รูปแบบของการคำนวณ) และรายละเอียดและการจำแนกประเภทของภาษาอย่างเป็นทางการ การนำไปใช้ในช่วงต้นอื่น ๆ ของการจับคู่รูปแบบได้แก่ภาษาSNOBOLซึ่งไม่ได้ใช้นิพจน์ทั่วไป แต่ใช้โครงสร้างการจับคู่รูปแบบของตัวเองแทน
นิพจน์ทั่วไปเข้าสู่การใช้ที่นิยมตั้งแต่ปี 1968 โดยใช้สองแบบ: การจับคู่รูปแบบในโปรแกรมแก้ไขข้อความ[6]และการวิเคราะห์ศัพท์ในคอมไพเลอร์ [7]ท่ามกลางการปรากฏตัวครั้งแรกของการแสดงผลปกติในรูปแบบโปรแกรมได้เมื่อเคน ธ อมป์สันสร้างสัญกรณ์ Kleene เข้าไปแก้ไขQEDเป็นวิธีที่จะตรงกับรูปแบบในไฟล์ข้อความ [6] [8] [9] [10]เพื่อความรวดเร็ว Thompson ได้ใช้การจับคู่นิพจน์ทั่วไปโดยการคอมไพล์แบบทันเวลา (JIT) กับโค้ดIBM 7094บนCompatible Time-Sharing Systemซึ่งเป็นตัวอย่างแรกเริ่มที่สำคัญของการคอมไพล์ JIT [11]ต่อมาเขาได้เพิ่มความสามารถนี้ให้กับ Unix editor edซึ่งในที่สุดก็นำไปสู่การใช้นิพจน์ทั่วไปของเครื่องมือค้นหาgrep ("grep" เป็นคำที่มาจากคำสั่งสำหรับการค้นหานิพจน์ทั่วไปในเอดิเตอร์ ed: ความหมาย "ค้นหาส่วนกลางสำหรับนิพจน์ทั่วไปและพิมพ์บรรทัดที่ตรงกัน") [12]ในช่วงเวลาเดียวกันกับที่ทอมป์สันพัฒนา QED กลุ่มนักวิจัยรวมถึงดักลาสทีรอสส์ได้ใช้เครื่องมือตามนิพจน์ทั่วไปที่ใช้สำหรับการวิเคราะห์ศัพท์ในการออกแบบคอมไพเลอร์ [7]g/re/p
หลายรูปแบบรูปแบบเดิมเหล่านี้แสดงออกปกติถูกนำมาใช้ในระบบปฏิบัติการยูนิกซ์[10]โปรแกรมที่เบลล์แล็บในปี 1970 รวมทั้งvi , lex , sed , AWKและexprและในโปรแกรมอื่น ๆ เช่นEmacs ต่อมา Regexes ถูกนำมาใช้โดยโปรแกรมต่างๆมากมายโดยรูปแบบแรกเริ่มเหล่านี้ได้รับการกำหนดมาตรฐานในมาตรฐานPOSIX.2ในปี 1992
ในช่วงปี 1980 ที่ regexes ซับซ้อนมากขึ้นเกิดขึ้นในPerlซึ่ง แต่เดิมมาจากห้องสมุด regex เขียนโดยเฮนรี่สเปนเซอร์ (1986) ซึ่งต่อมาเขียนการดำเนินการขั้นสูงนิพจน์ปกติสำหรับTcl [13]ไลบรารี Tcl เป็นการใช้งานNFA / DFAแบบไฮบริดที่มีคุณลักษณะด้านประสิทธิภาพที่ดีขึ้น โครงการซอฟแวร์ที่ได้นำ Tcl ดำเนินการแสดงออกปกติของสเปนเซอร์ ได้แก่PostgreSQL [14]ต่อมา Perl ได้ขยายในไลบรารีดั้งเดิมของ Spencer เพื่อเพิ่มคุณสมบัติใหม่ ๆ มากมาย [15]ส่วนหนึ่งของความพยายามในการออกแบบRaku (เดิมชื่อ Perl 6) คือการปรับปรุงการรวม regex ของ Perl และเพิ่มขอบเขตและความสามารถเพื่อให้สามารถกำหนดไวยากรณ์ของนิพจน์ที่แยกวิเคราะห์ได้ [16]ผลลัพธ์ที่ได้คือภาษาขนาดเล็กที่เรียกว่ากฎ Rakuซึ่งใช้ในการกำหนดไวยากรณ์ของ Raku รวมทั้งจัดหาเครื่องมือให้กับโปรแกรมเมอร์ในภาษานั้น ๆ กฎเหล่านี้ยังคงรักษาคุณลักษณะที่มีอยู่ของ regexes Perl 5.x แต่ยังอนุญาตให้ใช้นิยามสไตล์BNFของตัวแยกวิเคราะห์การสืบเชื้อสายซ้ำผ่านกฎย่อย
การใช้ regexes ในมาตรฐานข้อมูลที่มีโครงสร้างสำหรับการสร้างแบบจำลองเอกสารและฐานข้อมูลเริ่มต้นในทศวรรษที่ 1960 และขยายตัวในทศวรรษที่ 1980 เมื่อมาตรฐานอุตสาหกรรมเช่นISO SGML (ซึ่งถูกตั้งค่าโดย ANSI "GCA 101-1983") รวมเข้าด้วยกัน เคอร์เนลของมาตรฐานภาษาข้อกำหนดโครงสร้างประกอบด้วยนิพจน์ทั่วไป การใช้งานจะเห็นได้ชัดในไวยากรณ์กลุ่มองค์ประกอบDTD
เริ่มต้นในปี 1997 ฟิลิปเฮเซลพัฒนาPCRE (นิพจน์ปกติ Perl เข้ากันได้) ซึ่งพยายามที่จะเลียนแบบการทำงานอย่างใกล้ชิดของ Perl regex และถูกใช้โดยเครื่องมือที่ทันสมัยจำนวนมากรวมทั้งPHPและApache HTTP Server
ปัจจุบัน regexes ได้รับการสนับสนุนอย่างกว้างขวางในภาษาโปรแกรมโปรแกรมประมวลผลข้อความ (โดยเฉพาะlexers ) โปรแกรมแก้ไขข้อความขั้นสูงและโปรแกรมอื่น ๆ สนับสนุน Regex เป็นส่วนหนึ่งของห้องสมุดมาตรฐานของภาษาโปรแกรมจำนวนมากรวมทั้งJavaและงูหลามและถูกสร้างขึ้นในไวยากรณ์ของคนอื่น ๆ รวมทั้ง Perl และECMAScript การใช้งานฟังก์ชัน regex มักเรียกว่าregex engineและมีไลบรารีจำนวนหนึ่งสำหรับการใช้ซ้ำ ในช่วงปลายยุค 2010 หลาย บริษัท เริ่มที่จะฮาร์ดแวร์เสนอFPGA , [17] GPU [18]การใช้งานของPCREเข้ากันได้เครื่องมือ regexที่เร็วขึ้นเมื่อเทียบกับCPU การใช้งาน
แนวคิดพื้นฐาน
นิพจน์ทั่วไปมักเรียกว่ารูปแบบระบุชุดของสตริงที่จำเป็นสำหรับวัตถุประสงค์เฉพาะ วิธีง่ายๆในการระบุชุดสตริงที่ จำกัด คือการแสดงรายการองค์ประกอบหรือสมาชิก แต่มีวิธีการที่มักจะกระชับมากขึ้น: ยกตัวอย่างเช่นชุดที่มีสามสาย "ฮันเดล", "Händel" และ "Haendel" สามารถระบุโดยรูปแบบH(ä|ae?)ndel
; เราบอกว่ารูปแบบนี้ตรงกับสตริงทั้งสาม ในความเป็นทางการส่วนใหญ่หากมีนิพจน์ทั่วไปอย่างน้อยหนึ่งนิพจน์ที่ตรงกับชุดเฉพาะแสดงว่ามีนิพจน์ทั่วไปอื่น ๆ จำนวนไม่ จำกัด ที่จับคู่ด้วยเช่นกันข้อกำหนดจะไม่ซ้ำกัน พิธีการส่วนใหญ่จัดเตรียมการดำเนินการต่อไปนี้เพื่อสร้างนิพจน์ทั่วไป
- บูลีน "หรือ"
- แถบแนวตั้งทางเลือกแยก ตัวอย่างเช่น สามารถจับคู่ "สีเทา" หรือ "สีเทา"
gray|grey
- การจัดกลุ่ม
- วงเล็บใช้เพื่อกำหนดขอบเขตและลำดับความสำคัญของตัว ดำเนินการ (รวมถึงการใช้งานอื่น ๆ ) ตัวอย่างเช่น
gray|grey
และ เป็นรูปแบบที่เท่ากันซึ่งทั้งคู่อธิบายถึงชุดของ "สีเทา" หรือ "สีเทา"gr(a|e)y
- ปริมาณ
- ตัว ระบุปริมาณหลัง โทเค็น (เช่นอักขระ) หรือกลุ่มระบุความถี่ที่อนุญาตให้องค์ประกอบก่อนหน้าเกิดขึ้น ปริมาณที่พบมากที่สุดเป็น เครื่องหมายคำถาม
?
ที่ เครื่องหมายดอกจัน*
(มาจาก Kleene ดาว ) และ เครื่องหมายบวก+
( Kleene บวก )
?
เครื่องหมายคำถามแสดงถึงศูนย์หรือหนึ่งเหตุการณ์ที่เกิดขึ้นก่อนหน้านี้ ตัวอย่างเช่น colou?r
จับคู่ทั้ง "color" และ "color"*
เครื่องหมายดอกจันหมายถึงการเกิดขึ้นขององค์ประกอบก่อนหน้าเป็นศูนย์หรือมากกว่านั้น ตัวอย่างเช่น ab*c
จับคู่ "ac" "abc" "abbc" "abbbc" เป็นต้น+
เครื่องหมายบวกบ่งชี้เหตุการณ์ที่เกิดขึ้นอย่างน้อยหนึ่งครั้งขององค์ประกอบก่อนหน้า ตัวอย่างเช่น ab+c
จับคู่ "abc", "abbc", "abbbc" และอื่น ๆ แต่ไม่ใช่ "ac"{n}
[19]รายการก่อนหน้านี้ตรงกันทุกประการnครั้ง {min,}
[19]รายการก่อนหน้าตรงกับขั้นต่ำหรือมากกว่าครั้ง {,max}
[19]รายการก่อนหน้านี้ตรงกับเวลาสูงสุด {min,max}
[19]รายการก่อนหน้านี้ตรงกันอย่างน้อยครั้งต่ำสุดแต่ไม่เกินจำนวนครั้งสูงสุด
- สัญลักษณ์แทน
สัญลักษณ์แทน.
ตรงกับอักขระใด ๆ ตัวอย่างเช่นa.b
จับคู่สตริงใด ๆ ที่มี "a" ตามด้วยอักขระอื่น ๆ และตามด้วย "b" a.*b
จับคู่สตริงใด ๆ ที่มี "a" และตามด้วยอักขระ "b" ในภายหลัง
โครงสร้างเหล่านี้สามารถรวมกันเพื่อสร้างนิพจน์ที่ซับซ้อนตามอำเภอใจได้เช่นเดียวกับที่สามารถสร้างนิพจน์ทางคณิตศาสตร์จากตัวเลขและการดำเนินการ +, -, ×และ÷ ยกตัวอย่างเช่นH(ae?|ä)ndel
และมีทั้งรูปแบบที่ถูกต้องซึ่งตรงกับสายเดียวกับตัวอย่างก่อนหน้านี้H(a|ae|ä)ndel
H(ä|ae?)ndel
ไวยากรณ์ที่แม่นยำสำหรับนิพจน์ทั่วไปจะแตกต่างกันไปตามเครื่องมือและบริบท รายละเอียดเพิ่มเติมจะได้รับใน§ไวยากรณ์
ทฤษฎีภาษาที่เป็นทางการ
นิพจน์ปกติอธิบายภาษาปกติในทฤษฎีภาษาอย่างเป็นทางการ พวกเขามีพลังในการแสดงออกเช่นเดียวกับไวยากรณ์ทั่วไป
คำจำกัดความที่เป็นทางการ
นิพจน์ทั่วไปประกอบด้วยค่าคงที่ซึ่งแสดงถึงชุดของสตริงและสัญลักษณ์ตัวดำเนินการซึ่งแสดงถึงการดำเนินการเหนือชุดเหล่านี้ คำจำกัดความต่อไปนี้เป็นมาตรฐานและพบได้ในหนังสือเรียนส่วนใหญ่เกี่ยวกับทฤษฎีภาษาที่เป็นทางการ [20] [21]ด้วยอักษรจำกัดΣค่าคงที่ต่อไปนี้ถูกกำหนดให้เป็นนิพจน์ทั่วไป:
- ( ชุดว่าง ) ∅แสดงถึงชุด∅
- ( สตริงว่าง ) εแสดงถึงชุดที่มีเฉพาะสตริง "ว่าง" ซึ่งไม่มีอักขระเลย
- ( ตัวอักษร )
a
ในΣแสดงถึงชุดที่มีเฉพาะอักขระa .
ด้วยนิพจน์ทั่วไป R และ S การดำเนินการต่อไปนี้จะถูกกำหนดเพื่อสร้างนิพจน์ทั่วไป:
- ( concatenation )
(RS)
หมายถึงชุดของสตริงที่สามารถหาได้จากการต่อสตริงที่ยอมรับโดย R และสตริงที่ S ยอมรับ (ตามลำดับนั้น) ตัวอย่างเช่นให้ R แสดงว่า {"ab", "c"} และ S หมายถึง {"d", "ef"} จากนั้น(RS)
หมายถึง {"abd", "abef", "cd", "cef"} - ( alternation )
(R|S)
หมายถึงการรวมเซตของเซตที่อธิบายโดย R และ S เช่นถ้า R อธิบายว่า {"ab", "c"} และ S อธิบายถึง {"ab", "d", "ef"} นิพจน์จะ(R|S)
อธิบายถึง { "ab", "c", "d", "ef"} - ( Kleene ดาว )
(R*)
หมายถึงการที่เล็กที่สุดเซ็ตชุดอธิบายโดยRที่มีεและปิดภายใต้สตริง นี่คือชุดของสตริงทั้งหมดที่สามารถสร้างขึ้นโดยการเชื่อมต่อหมายเลข จำกัด ใด ๆ (รวมถึงศูนย์) ของสตริงจากชุดที่อธิบายโดย R ตัวอย่างเช่นถ้า R หมายถึง {"0", "1"} จะ(R*)
หมายถึงชุดของทั้งหมดสตริงไบนารีจำกัด(รวมถึงสตริงว่าง) ถ้า R หมายถึง {"ab", "c"}(R*)
แสดงว่า {ε, "ab", "c", "abab", "abc", "cab", "cc", "ababab", "abcab", .. }.
เพื่อหลีกเลี่ยงวงเล็บจะถือว่าดาวคลีนมีลำดับความสำคัญสูงสุดจากนั้นจึงเรียงต่อกันแล้วจึงสลับกัน หากไม่มีความคลุมเครือก็อาจละเว้นวงเล็บได้ ตัวอย่างเช่น(ab)c
สามารถเขียนเป็นabc
และa|(b(c*))
สามารถเขียนเป็นa|bc*
ไฟล์. หนังสือเรียนหลายเล่มใช้สัญลักษณ์∪, + หรือ∨สำหรับการสลับแทนแถบแนวตั้ง
ตัวอย่าง:
a|b*
หมายถึง {ε, "a", "b", "bb", "bbb", ... }(a|b)*
หมายถึงชุดของสตริงทั้งหมดที่ไม่มีสัญลักษณ์อื่นใดนอกจาก "a" และ "b" รวมถึงสตริงว่าง: {ε, "a", "b", "aa", "ab", "ba", "bb" , "aaa", ... }ab*(c|ε)
หมายถึงชุดของสตริงที่ขึ้นต้นด้วย "a" จากนั้นจึงเป็นศูนย์หรือมากกว่า "b" s และสุดท้ายคือเลือก "c": {"a", "ac", "ab", "abc", "abb", "abbc ", ... }(0|(1(01*0)*1))*
หมายถึงชุดของเลขฐานสองที่ทวีคูณเป็น 3: {ε, "0", "00", "11", "000", "011", "110", "0000", "0011", "0110" , "1001", "1100", "1111", "00000", ... }
พลังที่แสดงออกและความกะทัดรัด
ความหมายอย่างเป็นทางการของการแสดงออกปกติมีน้อยเกี่ยวกับวัตถุประสงค์และหลีกเลี่ยงการกำหนด?
และ+
-these สามารถแสดงเป็นดังนี้a+
= aa*
และ=a?
(a|ε)
บางครั้งสมบูรณ์ผู้ประกอบการจะมีการเพิ่มเพื่อให้การแสดงออกปกติทั่วไป ; นี่R คตรงกับสายทั่วΣ * ที่ไม่ตรงกับR โดยหลักการแล้วตัวดำเนินการส่วนเสริมนั้นซ้ำซ้อนเนื่องจากไม่ได้ให้อำนาจในการแสดงออกอีกต่อไป อย่างไรก็ตามมันสามารถทำให้นิพจน์ทั่วไปกระชับมากขึ้น - การกำจัดตัวดำเนินการส่วนเสริมเพียงตัวเดียวอาจทำให้ความยาวของมันเพิ่มขึ้นเป็นทวีคูณ [22] [23] [24]
การแสดงผลปกติในความรู้สึกนี้สามารถแสดงภาษาปกติว่าระดับของภาษาที่ยอมรับโดยออโต จำกัด กำหนด อย่างไรก็ตามมีความแตกต่างอย่างมีนัยสำคัญในความกะทัดรัด ภาษาทั่วไปบางคลาสสามารถอธิบายได้โดยออโตมาตา จำกัด ที่กำหนดซึ่งขนาดจะโตขึ้นแบบทวีคูณในขนาดของนิพจน์ทั่วไปที่สั้นที่สุดที่เทียบเท่ากัน ตัวอย่างมาตรฐานที่นี่เป็นภาษาL kประกอบด้วยสายทั่วตัวอักษร { , ข } ซึ่งk THรินสุดท้ายจดหมายเท่ากับ ในแง่หนึ่งนิพจน์ทั่วไปที่อธิบายL 4จะได้รับโดย.
การสรุปรูปแบบนี้เป็นL kให้นิพจน์:
ในทางกลับกันก็เป็นที่รู้จักกันว่าทุกคนแน่นอนหุ่นยนต์กำหนดยอมรับภาษาL kต้องมีอย่างน้อย 2 kรัฐ โชคดีที่มีการทำแผนที่อย่างง่ายจากนิพจน์ทั่วไปไปจนถึงออโตมาตา จำกัด แบบไม่กำหนดเฉพาะเจาะจง (NFAs) ทั่วไปที่ไม่ได้นำไปสู่การระเบิดขนาดนั้น ด้วยเหตุนี้จึงมักใช้ NFAs เป็นตัวแทนของภาษาปกติ NFAs มีรูปแบบที่เรียบง่ายของประเภท 3 ไวยากรณ์ของลำดับชั้นของชัม [20]
ในทางตรงกันข้ามมีหลายภาษาที่อธิบายได้ง่ายโดย DFA ซึ่งไม่ได้อธิบายง่ายๆว่าเป็นนิพจน์ทั่วไป ตัวอย่างเช่นการพิจารณาความถูกต้องของISBN ที่กำหนดต้องคำนวณโมดูลัสของฐานจำนวนเต็ม 11 และสามารถนำไปใช้กับ DFA 11 สถานะได้อย่างง่ายดาย อย่างไรก็ตามนิพจน์ทั่วไปเพื่อตอบปัญหาเดียวกันของการหารด้วย 11 มีความยาวอย่างน้อยหลายเมกะไบต์ [ ต้องการอ้างอิง ]
ด้วยนิพจน์ทั่วไปอัลกอริธึมการก่อสร้างของทอมป์สันจะคำนวณหุ่นยนต์ จำกัด ที่ไม่ได้กำหนดไว้เทียบเท่า แปลงไปในทิศทางตรงกันข้ามจะทำได้โดยอัลกอริทึมของ Kleene
สุดท้ายเป็นที่น่าสังเกตว่าเครื่องมือ "นิพจน์ทั่วไป" ในโลกแห่งความเป็นจริงจำนวนมากใช้คุณลักษณะที่ไม่สามารถอธิบายได้ด้วยนิพจน์ทั่วไปในความหมายของทฤษฎีภาษาที่เป็นทางการ แต่พวกเขาใช้regexes ดูด้านล่างสำหรับข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้
การตัดสินใจความเท่าเทียมกันของนิพจน์ทั่วไป
ดังที่เห็นในหลาย ๆ ตัวอย่างข้างต้นมีมากกว่าหนึ่งวิธีในการสร้างนิพจน์ทั่วไปเพื่อให้ได้ผลลัพธ์ที่เหมือนกัน
เป็นไปได้ที่จะเขียนอัลกอริทึมที่สำหรับสองนิพจน์ทั่วไปที่กำหนดให้ตัดสินใจว่าภาษาที่อธิบายนั้นเท่าเทียมกันหรือไม่ อัลกอริทึมจะลดนิพจน์แต่ละรายการให้เป็นเครื่องกำหนดสถานะ จำกัด ที่น้อยที่สุดและพิจารณาว่าเป็นไอโซมอร์ฟิก (เทียบเท่า) หรือไม่
กฎพีชคณิตสำหรับนิพจน์ทั่วไปสามารถหาได้โดยใช้วิธีการของ Gischer ซึ่งอธิบายได้ดีที่สุดพร้อมตัวอย่าง: เพื่อตรวจสอบว่า ( X + Y ) *และ ( X * Y * ) *แสดงถึงภาษาปกติเดียวกันหรือไม่สำหรับนิพจน์ทั่วไปทั้งหมดX , Yจำเป็นและเพียงพอที่จะตรวจสอบว่านิพจน์ทั่วไป ( a + b ) *และ ( a * b * ) *แสดงภาษาเดียวกันทับตัวอักษรΣ = { a , b } หรือไม่ โดยทั่วไปแล้วสมการE = Fระหว่างเงื่อนไขนิพจน์ทั่วไปที่มีตัวแปรจะถือในกรณีที่และเฉพาะในกรณีที่การสร้างอินสแตนซ์ของตัวแปรที่แตกต่างกันถูกแทนที่ด้วยค่าคงที่สัญลักษณ์ที่ต่างกัน [25] [26]
ความซ้ำซ้อนสามารถกำจัดได้โดยใช้Kleene starและตั้งค่าการรวมกันเพื่อค้นหานิพจน์ทั่วไปที่น่าสนใจซึ่งยังคงแสดงออกได้อย่างสมบูรณ์ แต่อาจ จำกัด การใช้งานได้ [ ต้องการคำชี้แจง ]นี่เป็นปัญหาที่ยากอย่างน่าประหลาดใจ เรียบง่ายเหมือนนิพจน์ทั่วไปไม่มีวิธีใดในการเขียนซ้ำอย่างเป็นระบบให้เป็นรูปแบบปกติ การขาดความจริงในอดีตที่ผ่านมาจะนำไปสู่ปัญหาความสูงดาว ในปีพ. ศ. 2534 Dexter Kozen ได้นำนิพจน์ทั่วไปมาใช้เป็นพีชคณิตแบบคลีนโดยใช้สัจพจน์สมการและฮอร์น [27]ในปีพ. ศ. 2507 Redko ได้พิสูจน์แล้วว่าไม่มีชุดใดของสัจพจน์ที่เท่าเทียมกันอย่างแท้จริงที่สามารถอธิบายลักษณะของพีชคณิตของภาษาปกติได้ [28]
ไวยากรณ์
regex รูปแบบที่ตรงกับเป้าหมายสตริง รูปแบบประกอบด้วยลำดับของอะตอม อะตอมเป็นจุดเดียวภายในรูปแบบนิพจน์ทั่วไปที่พยายามจับคู่กับสตริงเป้าหมาย อะตอมที่ง่ายที่สุดคือตัวอักษร แต่การจัดกลุ่มส่วนต่างๆของรูปแบบเพื่อให้ตรงกับอะตอมจะต้องใช้( )
เป็นอักขระเมตา Metacharacters ช่วยในรูปแบบ: อะตอม ; ตัวบอกปริมาณบอกจำนวนอะตอม (และเป็นตัวบอกปริมาณโลภหรือไม่) ตรรกะหรืออักขระซึ่งเสนอชุดของทางเลือกและอักขระ NOT เชิงตรรกะซึ่งลบล้างการมีอยู่ของอะตอม และการอ้างอิงย้อนกลับเพื่ออ้างถึงอะตอมก่อนหน้าของรูปแบบที่สมบูรณ์ของอะตอม การจับคู่จะเกิดขึ้นไม่ใช่เมื่ออะตอมทั้งหมดของสตริงถูกจับคู่ แต่เป็นเมื่อรูปแบบอะตอมทั้งหมดใน regex ตรงกัน แนวคิดคือการสร้างรูปแบบของอักขระขนาดเล็กสำหรับสตริงที่เป็นไปได้จำนวนมากแทนที่จะรวบรวมรายการความเป็นไปได้ตามตัวอักษรจำนวนมาก
ทั้งนี้ขึ้นอยู่กับหน่วยประมวลผล regex มีประมาณสิบสี่ metacharacters ตัวละครที่อาจจะหรืออาจจะไม่ได้ของพวกเขาที่แท้จริงความหมายตัวอักษรขึ้นอยู่กับบริบทหรือไม่ว่าพวกเขาจะ "หนี" คือนำหน้าด้วยลำดับหนี\
ในกรณีนี้เครื่องหมาย regexes สมัยใหม่และ POSIX ใช้อักขระเมตาบ่อยกว่าความหมายตามตัวอักษรดังนั้นเพื่อหลีกเลี่ยง "backslash-osis" หรือโรคไม้จิ้มฟันเอนจึงเป็นเรื่องที่สมเหตุสมผลที่จะต้องหลีกหนี metacharacter ไปยังโหมดตามตัวอักษร แต่เริ่มต้นจากนั้นมันสมเหตุสมผลกว่าที่จะมีอักขระสี่ตัวคร่อมสี่ตัว( )
และ{ }
เป็นตัวอักษรเป็นหลักและ "หลบหนี" ความหมายปกตินี้ให้กลายเป็นอักขระเมตาคาแร็กเตอร์ มาตรฐานทั่วไปใช้ทั้งสองอย่าง metacharacters ปกติและ {}[]()^$.|*+?
\
ตัวละครปกติที่กลายเป็น metacharacters เมื่อหนีอยู่และdswDSW
N
ตัวคั่น
เมื่อป้อน regex ในภาษาโปรแกรมอาจแสดงเป็นสตริงตามตัวอักษรตามปกติดังนั้นจึงมักจะยกมา นี้เป็นเรื่องธรรมดาใน C, Java และงูหลามตัวอย่างเช่นที่ regex ไม่ถูกป้อนเป็นre
"re"
อย่างไรก็ตามมักเขียนด้วยเครื่องหมายทับเป็นตัวคั่นเช่นเดียว/re/
กับนิพจน์re
ทั่วไป สิ่งนี้เกิดขึ้นในedโดยที่/
คำสั่งเอดิเตอร์สำหรับการค้นหาและ/re/
สามารถใช้นิพจน์เพื่อระบุช่วงของบรรทัด (ตรงกับรูปแบบ) ซึ่งสามารถใช้ร่วมกับคำสั่งอื่น ๆ ในด้านใดด้านหนึ่งซึ่งมีชื่อเสียงมากที่สุดg/re/p
เช่นเดียวกับในgrep ("global regex print ") ซึ่งรวมอยู่ในระบบปฏิบัติการที่ใช้Unixส่วนใหญ่เช่นลีนุกซ์ดิสทริบิวชัน สนธิสัญญาที่คล้ายกันคือใช้ในsedที่ค้นหาและแทนที่จะได้รับโดยรูปแบบและสามารถเข้าร่วมด้วยเครื่องหมายจุลภาคเพื่อระบุช่วงของสายในขณะที่s/re/replacement/
/re1/,/re2/
สัญกรณ์นี้เป็นที่รู้จักกันดีโดยเฉพาะเนื่องจากใช้ในPerlซึ่งเป็นส่วนหนึ่งของไวยากรณ์ที่แตกต่างจากตัวอักษรสตริงปกติ ในบางกรณีเช่น sed และ Perl สามารถใช้ตัวคั่นทางเลือกเพื่อหลีกเลี่ยงการชนกับเนื้อหาและเพื่อหลีกเลี่ยงการหลีกเลี่ยงการเกิดขึ้นของอักขระตัวคั่นในเนื้อหา ตัวอย่างเช่นใน sed คำสั่งs,/,X,
จะแทนที่ a /
ด้วยX
โดยใช้เครื่องหมายจุลภาคเป็นตัวคั่น
มาตรฐาน
IEEE POSIXมาตรฐานมีสามชุดของการปฏิบัติตาม: BRE (นิพจน์พื้นฐานปกติ) [29] ERE (ขยายนิพจน์ปกติ) และSRE (นิพจน์ปกติเรียบง่าย) SRE จะเลิก , [30]ในความโปรดปรานของ BRE ขณะที่ทั้งสองให้เข้ากันได้ย้อนหลัง ส่วนย่อยด้านล่างที่ครอบคลุมคลาสอักขระใช้กับทั้ง BRE และ ERE
BRE และ ERE ทำงานร่วมกัน ERE เพิ่ม?
, +
และ|
และมันไม่จำเป็นต้องที่จะหลบหนี metacharacters ( )
และ{ }
ซึ่งจะต้องอยู่ใน BRE นอกจากนี้ตราบใดที่มีการปฏิบัติตามไวยากรณ์มาตรฐาน POSIX สำหรับ regexes อาจมีและมักจะเป็นไวยากรณ์เพิ่มเติมเพื่อรองรับแอปพลิเคชันที่เฉพาะเจาะจง (แต่เป็นไปตามมาตรฐาน POSIX) แม้ว่า POSIX.2 จะไม่ได้กำหนดเฉพาะการใช้งานบางส่วน แต่ BRE และ ERE ก็มี "มาตรฐาน" ซึ่งนับตั้งแต่นั้นมาได้ถูกนำมาใช้เป็นไวยากรณ์เริ่มต้นของเครื่องมือต่างๆโดยที่ตัวเลือกโหมด BRE หรือ ERE มักเป็นตัวเลือกที่รองรับ ตัวอย่างเช่นGNU grep
มีตัวเลือกต่อไปนี้: " grep -E
" สำหรับ ERE และ " grep -G
" สำหรับ BRE (ค่าเริ่มต้น) และ " grep -P
" สำหรับPerl regexes
Perl regexes ได้กลายเป็นมาตรฐานโดยพฤตินัยโดยมีชุดนิพจน์อะตอมที่หลากหลายและทรงพลัง Perl ไม่มีระดับ "พื้นฐาน" หรือ "ขยาย" เช่นเดียวกับใน POSIX EREs ( )
และ{ }
ถือว่าเป็นอักขระเมตาคาแร็กเตอร์เว้นแต่จะหลบหนี metacharacters อื่น ๆ เป็นที่รู้กันว่าเป็นตัวอักษรหรือสัญลักษณ์ตามบริบทเพียงอย่างเดียว ฟังก์ชันการทำงานเพิ่มเติมรวมถึงการจับคู่ขี้เกียจ , backreferencesชื่อกลุ่มการจับภาพและrecursiveรูปแบบ
POSIX พื้นฐานและแบบขยาย
ในPOSIXมาตรฐานพื้นฐานปกติไวยากรณ์ ( BRE ) กำหนดว่าmetacharacters ( )
และ{ }
จะกำหนด\(\)
และ\{\}
ในขณะที่การขยายปกติไวยากรณ์ ( ERE ) ไม่ได้
Metacharacter | คำอธิบาย |
---|---|
^ | จับคู่ตำแหน่งเริ่มต้นภายในสตริง ในเครื่องมือแบบเส้นจะจับคู่ตำแหน่งเริ่มต้นของเส้นใดก็ได้ |
. | จับคู่อักขระเดี่ยวใด ๆ (แอปพลิเคชันจำนวนมากไม่รวมการขึ้นบรรทัดใหม่และอักขระใดที่ถือว่าขึ้นบรรทัดใหม่นั้นเป็นรสชาติ - การเข้ารหัสอักขระและเฉพาะแพลตฟอร์ม แต่จะถือว่าปลอดภัยที่จะสมมติว่ามีอักขระฟีดบรรทัดรวมอยู่ด้วย) ภายในนิพจน์วงเล็บ POSIX อักขระจุดจะตรงกับจุดตามตัวอักษร ตัวอย่างเช่นa.c จับคู่ "abc" เป็นต้น แต่[a.c] จับคู่เฉพาะ "a", "." หรือ "c" |
[ ] | นิพจน์วงเล็บ จับคู่อักขระเดี่ยวที่อยู่ในวงเล็บ ตัวอย่างเช่น[abc] จับคู่ "a" "b" หรือ "c" [a-z] ระบุช่วงที่ตรงกับตัวอักษรพิมพ์เล็กตั้งแต่ "a" ถึง "z" สามารถผสมแบบฟอร์มเหล่านี้ได้: [abcx-z] จับคู่ "a", "b", "c", "x", "y" หรือ "z" ตามที่[a-cx-z] กำหนด
|
[^ ] | จับคู่อักขระเดี่ยวที่ไม่มีอยู่ในวงเล็บ ตัวอย่างเช่น[^abc] จับคู่อักขระอื่น ๆ ที่ไม่ใช่ "a", "b" หรือ "c" [^a-z] จับคู่อักขระเดี่ยวใด ๆ ที่ไม่ใช่อักษรตัวพิมพ์เล็กตั้งแต่ "a" ถึง "z" ในทำนองเดียวกันสามารถผสมอักขระและช่วงตามตัวอักษรได้ |
$ | จับคู่ตำแหน่งสิ้นสุดของสตริงหรือตำแหน่งก่อนขึ้นบรรทัดใหม่ที่สิ้นสุดสตริง ในเครื่องมือแบบเส้นจะจับคู่ตำแหน่งสิ้นสุดของบรรทัดใดก็ได้ |
( ) | กำหนดนิพจน์ย่อยที่ทำเครื่องหมายไว้ สตริงที่ตรงกับในวงเล็บสามารถเรียกคืนได้ในภายหลัง (ดูรายการถัดไป) นิพจน์ย่อยที่ทำเครื่องหมายไว้เรียกอีกอย่างว่าบล็อกหรือกลุ่มการจับภาพ โหมด BRE ต้อง\n \( \) |
\n | จับคู่สิ่งที่นิพจน์ย่อยที่ทำเครื่องหมายnจับคู่โดยที่nเป็นตัวเลขตั้งแต่ 1 ถึง 9 โครงสร้างนี้ถูกกำหนดไว้อย่างคลุมเครือในมาตรฐาน POSIX.2 เครื่องมือบางอย่างอนุญาตให้อ้างอิงกลุ่มการจับภาพมากกว่าเก้ากลุ่ม หรือที่เรียกว่า backreference |
* | จับคู่องค์ประกอบก่อนหน้าเป็นศูนย์หรือมากกว่าครั้ง ตัวอย่างเช่นab*c จับคู่ "ac", "abc", "abbbc" ฯลฯ[xyz]* ตรงกับ "", "x", "y", "z", "zx", "zyx", "xyzzy" และอื่น ๆ (ab)* จับคู่ "", "ab", "abab", "ababab" และอื่น ๆ |
{m,n} | จับคู่องค์ประกอบก่อนหน้าอย่างน้อยmและไม่เกินnครั้ง ตัวอย่างเช่นa{3,5} จับคู่เฉพาะ "aaa" "aaaa" และ "aaaaa" สิ่งนี้ไม่พบใน regexes รุ่นเก่าบางส่วน โหมด BRE \{m,n\} ต้อง |
ตัวอย่าง:
.at
จับคู่สตริงอักขระสามตัวที่ลงท้ายด้วย "at" รวมถึง "hat" "cat" และ "bat"[hc]at
จับคู่ "หมวก" และ "แมว"[^b]at
จับคู่สตริงทั้งหมดที่จับคู่โดย.at
ยกเว้น "ค้างคาว"[^hc]at
จับคู่สตริงทั้งหมดที่จับคู่โดย.at
อื่นที่ไม่ใช่ "หมวก" และ "แมว"^[hc]at
จับคู่ "หมวก" และ "แมว" แต่จะอยู่ที่จุดเริ่มต้นของสตริงหรือบรรทัดเท่านั้น[hc]at$
จับคู่ "หมวก" และ "แมว" แต่จะอยู่ที่ส่วนท้ายของสตริงหรือบรรทัดเท่านั้น\[.\]
จับคู่อักขระเดี่ยวใด ๆ ที่ล้อมรอบด้วย "[" และ "]" เนื่องจากวงเล็บจะเป็น Escape ตัวอย่างเช่น "[a]" และ "[b]"s.*
จับคู่ตามด้วยอักขระศูนย์ขึ้นไปตัวอย่างเช่น "s" และ "saw" และ "seed"
POSIX ขยาย
ความหมายของอักขระที่หลีกเลี่ยงด้วยแบ็กสแลชจะกลับรายการสำหรับอักขระบางตัวในไวยากรณ์POSIX Extended Regular Expression ( ERE ) ด้วยไวยากรณ์นี้แบ็กสแลชจะทำให้ metacharacter ได้รับการปฏิบัติเป็นอักขระตามตัวอักษร ดังนั้นสำหรับตัวอย่างเช่น\( \)
อยู่ในขณะนี้( )
และอยู่ในขณะนี้\{ \}
{ }
นอกจากนี้การสนับสนุนจะถูกลบออกสำหรับการอ้างอิงย้อนกลับและเพิ่มอักขระเมตาต่อไปนี้:\n
Metacharacter | คำอธิบาย |
---|---|
? | จับคู่องค์ประกอบก่อนหน้าเป็นศูนย์หรือครั้งเดียว ตัวอย่างเช่นab?c จับคู่เฉพาะ "ac" หรือ "abc" |
+ | จับคู่องค์ประกอบก่อนหน้าอย่างน้อยหนึ่งครั้ง ตัวอย่างเช่นab+c จับคู่ "abc", "abbc", "abbbc" และอื่น ๆ แต่ไม่ใช่ "ac" |
| | ตัวดำเนินการตัวเลือก (หรือที่เรียกว่า alternation หรือ set union) จะจับคู่นิพจน์ก่อนหรือนิพจน์หลังตัวดำเนินการ ตัวอย่างเช่นabc|def จับคู่ "abc" หรือ "def" |
ตัวอย่าง:
[hc]?at
จับคู่ "at" "hat" และ "cat"[hc]*at
จับคู่ "at", "hat", "cat", "hhat", "chat", "hcat", "cchchat" และอื่น ๆ[hc]+at
จับคู่ "hat", "cat", "hhat", "chat", "hcat", "cchchat" และอื่น ๆ แต่ไม่ใช่ "at"cat|dog
จับคู่ "แมว" หรือ "สุนัข"
POSIX ขยายนิพจน์ปกติมักจะสามารถใช้กับสาธารณูปโภค Unix ที่ทันสมัยโดยรวมบรรทัดคำสั่งธง-E
คลาสตัวละคร
คลาสอักขระเป็นแนวคิด regex พื้นฐานที่สุดหลังจากการจับคู่ตามตัวอักษร ทำให้ลำดับอักขระเล็ก ๆ หนึ่งตัวตรงกับชุดอักขระที่ใหญ่กว่า ตัวอย่างเช่นสามารถแทนตัวอักษรตัวพิมพ์ใหญ่ในตัวอักษรภาษาอังกฤษและอาจหมายถึงตัวเลขใดก็ได้ คลาสตัวละครนำไปใช้กับทั้งระดับ POSIX[A-Z]
\d
เมื่อระบุช่วงของอักขระเช่น(เช่นตัวพิมพ์เล็กไปจนถึงตัวพิมพ์ใหญ่) การตั้งค่าโลแคลของคอมพิวเตอร์จะกำหนดเนื้อหาตามลำดับตัวเลขของการเข้ารหัสอักขระ พวกเขาสามารถเก็บตัวเลขในลำดับนั้นหรือสั่งซื้อสินค้าอาจจะabc ... zABC ... ZหรือaAbBcC ... ZZ ดังนั้นมาตรฐาน POSIX จึงกำหนดคลาสอักขระซึ่งจะทราบโดยตัวประมวลผล regex ที่ติดตั้ง คำจำกัดความเหล่านั้นอยู่ในตารางต่อไปนี้:[a-Z]
a
Z
POSIX | ไม่ได้มาตรฐาน | Perl / Tcl | เป็นกลุ่ม | Java | แอสกี | คำอธิบาย |
---|---|---|---|---|---|---|
[:ascii:] [31] | \p{ASCII} | [\x00-\x7F] | อักขระ ASCII | |||
[:alnum:] | \p{Alnum} | [A-Za-z0-9] | อักขระที่เป็นตัวอักษรและตัวเลข | |||
[:word:] [31] | \w | \w | \w | [A-Za-z0-9_] | อักขระตัวเลขและตัวอักษรบวก "_" | |
\W | \W | \W | [^A-Za-z0-9_] | อักขระที่ไม่ใช่คำ | ||
[:alpha:] | \a | \p{Alpha} | [A-Za-z] | อักขระตามตัวอักษร | ||
[:blank:] | \s | \p{Blank} | [ \t] | เว้นวรรคและแท็บ | ||
\b | \< \> | \b | (?<=\W)(?=\w)|(?<=\w)(?=\W) | ขอบเขตของคำ | ||
\B | (?<=\W)(?=\W)|(?<=\w)(?=\w) | ขอบเขตที่ไม่ใช่คำ | ||||
[:cntrl:] | \p{Cntrl} | [\x00-\x1F\x7F] | ควบคุมอักขระ | |||
[:digit:] | \d | \d | \p{Digit} หรือ \d | [0-9] | ตัวเลข | |
\D | \D | \D | [^0-9] | ไม่ใช่ตัวเลข | ||
[:graph:] | \p{Graph} | [\x21-\x7E] | อักขระที่มองเห็นได้ | |||
[:lower:] | \l | \p{Lower} | [a-z] | อักษรตัวพิมพ์เล็ก | ||
[:print:] | \p | \p{Print} | [\x20-\x7E] | อักขระที่มองเห็นได้และอักขระเว้นวรรค | ||
[:punct:] | \p{Punct} | [][!"#$%&'()*+,./:;<=>?@\^_`{|}~-] | อักขระเครื่องหมายวรรคตอน | |||
[:space:] | \s | \_s | \p{Space} หรือ \s | [ \t\r\n\v\f] | อักขระเว้นวรรค | |
\S | \S | \S | [^ \t\r\n\v\f] | อักขระที่ไม่ใช่ช่องว่าง | ||
[:upper:] | \u | \p{Upper} | [A-Z] | ตัวอักษรตัวพิมพ์ใหญ่ | ||
[:xdigit:] | \x | \p{XDigit} | [A-Fa-f0-9] | เลขฐานสิบหก |
คลาสอักขระ POSIX สามารถใช้ได้ภายในนิพจน์วงเล็บเท่านั้น ตัวอย่างเช่นจับคู่ตัวอักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก "a" และ "b"[[:upper:]ab]
คลาสที่ไม่ใช่ POSIX เพิ่มเติมที่เครื่องมือบางอย่างเข้าใจคือซึ่งโดยปกติจะกำหนดเป็นเครื่องหมายบวกขีดล่าง สิ่งนี้สะท้อนให้เห็นถึงความจริงที่ว่าในภาษาโปรแกรมหลายภาษาเหล่านี้เป็นอักขระที่อาจใช้ในตัวระบุ ตัวแก้ไขVimแยกความแตกต่างของคลาสwordและword-head เพิ่มเติม (โดยใช้สัญกรณ์และ) เนื่องจากในภาษาการเขียนโปรแกรมจำนวนมากอักขระที่สามารถเริ่มตัวระบุจะไม่เหมือนกับที่สามารถเกิดขึ้นในตำแหน่งอื่น ๆ : โดยทั่วไปตัวเลขจะถูกยกเว้นดังนั้นตัวระบุ จะมีลักษณะเหมือนหรือในสัญกรณ์ POSIX[:word:]
[:alnum:]
\w
\h
\h\w*
[[:alpha:]_][[:alnum:]_]*
โปรดสังเกตว่าสิ่งที่คลาสอักขระเรียกมาตรฐาน regex ของ POSIX มักเรียกว่าคลาสอักขระ POSIXในรสชาติ regex อื่น ๆ ที่รองรับ กับส่วนใหญ่รสชาติ regex อื่น ๆ ในระยะตัวละครคลาสถูกนำมาใช้เพื่ออธิบายสิ่งที่เรียก POSIX แสดงออกวงเล็บ
Perl และ PCRE
เนื่องจากความสามารถในการแสดงออกและความสะดวกในการอ่าน (สัมพัทธ์) ยูทิลิตี้และภาษาโปรแกรมอื่น ๆ จึงนำไวยากรณ์ที่คล้ายกับPerl มาใช้เช่นJava , JavaScript , Julia , Python , Ruby , Qt , .NET Frameworkของ Microsoft และXML สคีมา ภาษาและเครื่องมือบางอย่างเช่นBoostและPHPรองรับ regex หลายรสชาติ การใช้งาน regex Perl-derivative จะไม่เหมือนกันและโดยปกติจะใช้คุณลักษณะย่อยที่พบใน Perl 5.0 ซึ่งเผยแพร่ในปี 1994 บางครั้ง Perl จะรวมคุณลักษณะที่พบในภาษาอื่น ๆ ตัวอย่างเช่น Perl 5.10 ใช้ส่วนขยายทางวากยสัมพันธ์ที่พัฒนาขึ้นใน PCRE และ Python [32]
ขี้เกียจจับคู่
ในหลามและบางส่วนการใช้งานอื่น ๆ (เช่น Java) สามปริมาณที่พบบ่อย ( *
, +
และ?
) มีความโลภโดยค่าเริ่มต้นเพราะพวกเขาตรงกับตัวละครมากที่สุดเท่าที่เป็นไปได้ [33]นิพจน์ทั่วไป".+"
(รวมถึงเครื่องหมายอัญประกาศคู่) ที่ใช้กับสตริง
"แกนีมีด" เขากล่าวต่อ "เป็นดวงจันทร์ที่ใหญ่ที่สุดในระบบสุริยะ"
ตรงกับสายทั้งหมด (เพราะทั้งเส้นเริ่มต้นและจบลงด้วยการอ้างดับเบิล) "Ganymede,"
แทนของการจับคู่เท่านั้นส่วนแรก ปริมาณดังกล่าวอาจอย่างไรจะทำขี้เกียจหรือน้อยที่สุดหรือไม่เต็มใจที่จับคู่เป็นตัวอักษรไม่กี่ที่เป็นไปได้โดยการผนวกเครื่องหมายคำถาม: ตรงเท่านั้น".+?"
[33]"Ganymede,"
อย่างไรก็ตามประโยคทั้งหมดยังสามารถจับคู่ได้ในบางสถานการณ์ ตัวดำเนินการเครื่องหมายคำถามจะไม่เปลี่ยนความหมายของตัวดำเนินการจุดดังนั้นจึงยังสามารถจับคู่อัญประกาศคู่ในอินพุตได้ รูปแบบเช่น".*?" EOF
จะยังคงตรงกับอินพุตทั้งหมดหากนี่คือสตริง:
"แกนีมีด" เขากล่าวต่อ "เป็นดวงจันทร์ที่ใหญ่ที่สุดในระบบสุริยะ" EOF
เพื่อให้แน่ใจว่าเครื่องหมายคำพูดคู่ไม่สามารถเป็นส่วนหนึ่งของการจับคู่ได้ต้องเปลี่ยนจุด (เช่น"[^"]*"
) สิ่งนี้จะจับคู่ส่วนข้อความที่ยกมาโดยไม่มีเครื่องหมายอัญประกาศคู่เพิ่มเติม (โดยการลบความเป็นไปได้ในการจับคู่คำต่อท้ายคงที่กล่าวคือ"
สิ่งนี้ได้เปลี่ยนการจับคู่แบบขี้เกียจเป็นการจับคู่แบบโลภดังนั้นจึง?
ไม่จำเป็นต้องใช้อีกต่อไป) [ ต้องการอ้างอิง ]
การจับคู่ที่เป็นไปได้
ใน Java ตัวระบุปริมาณอาจถูกทำให้เป็นเจ้าของได้โดยการต่อท้ายเครื่องหมายบวกซึ่งจะปิดใช้งานการสำรองข้อมูล (ในเอนจินการย้อนรอย) แม้ว่าการทำเช่นนั้นจะทำให้การจับคู่โดยรวมประสบความสำเร็จ: [34]ในขณะที่ regex ".*"
นำไปใช้กับสตริง
"แกนีมีด" เขากล่าวต่อ "เป็นดวงจันทร์ที่ใหญ่ที่สุดในระบบสุริยะ"
ตรงกับสายทั้งหมด, regex ไม่".*+"
ไม่ไม่ตรงกับที่ทุกคนเพราะกินการป้อนข้อมูลรวมทั้งในขั้นตอนสุดท้าย.*+
"
ดังนั้นตัวระบุจำนวนที่เป็นเจ้าของจึงมีประโยชน์มากที่สุดกับคลาสอักขระที่ถูกลบเช่น"[^"]*+"
ซึ่งจะจับคู่"Ganymede,"
เมื่อนำไปใช้กับสตริงเดียวกัน
อีกส่วนขยายทั่วไปที่ให้บริการฟังก์ชันเดียวกันคือการจัดกลุ่มอะตอมซึ่งปิดใช้งานการย้อนกลับสำหรับกลุ่มในวงเล็บ ไวยากรณ์ทั่วไปคือ(?> กลุ่ม) ตัวอย่างเช่น while ^ (wi | w) i $ตรงกันทั้งคู่ wiและ wii , ^ (?> wi | w) i $เท่านั้นที่ตรงกัน wiiเนื่องจากเครื่องยนต์ถูกห้ามไม่ให้ย้อนรอยและลองตั้งค่ากลุ่มเป็น "w" [35]
ตัวระบุปริมาณที่เป็นไปได้นั้นง่ายต่อการใช้งานมากกว่าตัวระบุปริมาณที่โลภและขี้เกียจและโดยปกติแล้วจะมีประสิทธิภาพมากกว่าในรันไทม์ [34]
รูปแบบสำหรับภาษาที่ไม่ใช่ภาษาปกติ
คุณสมบัติมากมายที่พบในไลบรารีนิพจน์ทั่วไปสมัยใหม่แทบทั้งหมดให้พลังในการแสดงออกที่เหนือกว่าภาษาทั่วไป ตัวอย่างเช่นการใช้งานจำนวนมากอนุญาตให้จัดกลุ่มนิพจน์ย่อยด้วยวงเล็บและเรียกคืนค่าที่ตรงกันในนิพจน์เดียวกัน (การอ้างอิงกลับ ) ซึ่งหมายความว่ารูปแบบสามารถจับคู่สตริงของคำซ้ำ ๆ เช่น "papa" หรือ "WikiWiki" ที่เรียกว่าสี่เหลี่ยมในทฤษฎีภาษาทางการ (.+)\1
รูปแบบสำหรับสตริงเหล่านี้คือ
ภาษาของสี่เหลี่ยมไม่ปกติและไม่เป็นมันบริบทฟรีเนื่องจากการแทรกสูบน้ำ อย่างไรก็ตามการจับคู่แบบที่มีจำนวนมากมายของ backreferences เช่นการสนับสนุนโดยเครื่องมือที่ทันสมัยจำนวนมากยังคงเป็นบริบทที่สำคัญ [36]ปัญหาทั่วไปของการจับคู่การอ้างอิงย้อนกลับจำนวนเท่าใดก็ได้คือNP-completeซึ่งเพิ่มขึ้นอย่างทวีคูณตามจำนวนกลุ่มแบ็คอ้างอิงที่ใช้ [37]
อย่างไรก็ตามเครื่องมือไลบรารีและเอ็นจิ้นจำนวนมากที่ให้การสร้างดังกล่าวยังคงใช้คำว่านิพจน์ทั่วไปสำหรับรูปแบบของพวกเขา สิ่งนี้นำไปสู่ระบบการตั้งชื่อที่คำว่านิพจน์ทั่วไปมีความหมายแตกต่างกันในทฤษฎีภาษาที่เป็นทางการและการจับคู่รูปแบบ ด้วยเหตุนี้บางคนจึงใช้คำว่าregex , regexpหรือเพียงแค่รูปแบบเพื่ออธิบายความหลัง Larry Wallผู้เขียนภาษาโปรแกรม Perl เขียนในบทความเกี่ยวกับการออกแบบRaku :
"นิพจน์ทั่วไป" […] เกี่ยวข้องเพียงเล็กน้อยกับนิพจน์ทั่วไปจริง อย่างไรก็ตามคำนี้เติบโตขึ้นพร้อมกับความสามารถของเครื่องมือจับคู่รูปแบบของเราดังนั้นฉันจะไม่พยายามต่อสู้กับความจำเป็นทางภาษาที่นี่ อย่างไรก็ตามโดยทั่วไปฉันจะเรียกพวกเขาว่า "regexes" (หรือ "regexen" เมื่อฉันอยู่ในอารมณ์แองโกล - แซกซอน) [16]
การยืนยัน | ดูเบื้องหลัง | มองไปข้างหน้า |
---|---|---|
บวก | (? <= รูปแบบ ) | (? = รูปแบบ ) |
เชิงลบ | (? แบบ ) | (? !แบบ ) |
มองข้างหลังและมองไปข้างหน้าการยืนยัน ในนิพจน์ทั่วไปของPerl |
คุณสมบัติอื่น ๆ ที่ไม่พบในการอธิบายภาษาทั่วไป ได้แก่ การยืนยัน ซึ่งรวมถึงที่แพร่หลาย ^และ $เช่นเดียวกับส่วนขยายที่ซับซ้อนมากขึ้นเช่น lookaround พวกเขากำหนดรอบของการจับคู่และไม่รั่วไหลในการจับคู่ซึ่งเป็นคุณลักษณะที่เกี่ยวข้องกับกรณีการใช้งานของการค้นหาสตริงเท่านั้น บางคนสามารถจำลองเป็นภาษาปกติได้โดยถือว่าสภาพแวดล้อมเป็นส่วนหนึ่งของภาษาเช่นกัน [38]
การใช้งานและเวลาทำงาน
มีอัลกอริทึมที่แตกต่างกันอย่างน้อยสามรายการที่ตัดสินว่า regex ที่ระบุตรงกับสตริงหรือไม่และอย่างไร
สิ่งที่เก่าแก่ที่สุดและเร็วที่สุดนั้นอาศัยผลลัพธ์ในทฤษฎีภาษาที่เป็นทางการซึ่งอนุญาตให้ทุก ๆตัวที่ไม่ จำกัด ขอบเขตของออโตเมตัน (NFA) เปลี่ยนเป็นหุ่นยนต์ จำกัด (DFA) แบบกำหนดได้ DFA สามารถสร้างขึ้นอย่างชัดเจนจากนั้นรันบนสตริงอินพุตที่เป็นผลลัพธ์ทีละสัญลักษณ์ การสร้าง DFA สำหรับนิพจน์ทั่วไปของขนาดmมีเวลาและต้นทุนหน่วยความจำเท่ากับO (2 ม. ) แต่สามารถรันบนสตริงขนาดnในเวลาO ( n ) โปรดทราบว่าขนาดของนิพจน์เป็นขนาดหลังจากตัวย่อเช่นตัวระบุจำนวนตัวเลขได้ถูกขยาย
อีกทางเลือกหนึ่งคือการจำลอง NFA โดยตรงโดยสร้างสถานะ DFA ตามความต้องการเป็นหลักจากนั้นจึงทิ้งในขั้นตอนต่อไป สิ่งนี้ช่วยให้ DFA มีนัยสำคัญและหลีกเลี่ยงต้นทุนการก่อสร้างแบบเอ็กซ์โพเนนเชียล แต่ต้นทุนการดำเนินการเพิ่มขึ้นเป็นO ( mn ) วิธีการที่ชัดเจนเรียกว่าอัลกอริทึม DFA และวิธีการโดยนัยของอัลกอริทึม NFA การเพิ่มแคชลงในอัลกอริทึม NFA มักเรียกว่าอัลกอริทึม "lazy DFA" หรือเพียงแค่อัลกอริทึม DFA โดยไม่สร้างความแตกต่าง อัลกอริทึมเหล่านี้รวดเร็ว แต่การใช้เพื่อเรียกคืนนิพจน์ย่อยที่จัดกลุ่มการหาจำนวนที่ขี้เกียจและคุณลักษณะที่คล้ายกันนั้นยุ่งยาก [39] [40]การใช้งานสมัยใหม่รวมถึงตระกูล re1-re2-sregex ตามรหัสของ Cox
อัลกอริทึมที่สามคือการตรงกับรูปแบบกับสายป้อนโดยย้อนรอย อัลกอริทึมนี้เรียกโดยทั่วไปว่า NFA แต่คำศัพท์นี้อาจทำให้สับสนได้ เวลาในการทำงานอาจเป็นเลขชี้กำลังซึ่งการนำไปใช้งานอย่างง่ายจะแสดงเมื่อจับคู่กับนิพจน์เช่นนั้นมีทั้งการหาปริมาณแบบสลับและแบบไม่ถูกผูกมัดและบังคับให้อัลกอริทึมพิจารณาจำนวนกรณีย่อยที่เพิ่มขึ้นแบบทวีคูณ ลักษณะการทำงานนี้อาจทำให้เกิดปัญหาด้านความปลอดภัยที่เรียกว่าRegular expression Denial of Service (ReDoS)(a|aa)*b
แม้ว่าการใช้งานย้อนรอยจะให้การรับประกันแบบเอ็กซ์โพเนนเชียลในกรณีที่เลวร้ายที่สุด แต่ก็ให้ความยืดหยุ่นและพลังในการแสดงออกที่ดีกว่ามาก ตัวอย่างเช่นการนำไปใช้งานใด ๆ ที่อนุญาตให้ใช้การอ้างอิงย้อนกลับหรือใช้ส่วนขยายต่างๆที่ Perl นำมาใช้จะต้องมีการติดตามย้อนกลับบางประเภท การใช้งานบางอย่างพยายามให้อัลกอริทึมที่ดีที่สุดโดยการเรียกใช้อัลกอริทึม DFA ที่รวดเร็วก่อนและเปลี่ยนกลับไปใช้อัลกอริธึมการย้อนรอยที่อาจช้าลงก็ต่อเมื่อพบการอ้างอิงย้อนกลับในระหว่างการแข่งขัน GNU grep (และ gnulib DFA) ใช้กลยุทธ์ดังกล่าว [41]
อัลกอริธึมรันไทม์ Sublinear ทำได้โดยใช้อัลกอริทึมที่ใช้Boyer-Moore (BM)และเทคนิคการเพิ่มประสิทธิภาพ DFA ที่เกี่ยวข้องเช่นการสแกนย้อนกลับ [42] GNU grep ซึ่งรองรับไวยากรณ์และส่วนขยาย POSIX ที่หลากหลายใช้ BM สำหรับการกรองล่วงหน้าก่อนผ่านไปแล้วจึงใช้ DFA โดยนัย Wu agrepซึ่งใช้การจับคู่โดยประมาณรวมการกรองล่วงหน้าเข้ากับ DFA ใน BDM (การจับคู่ DAWG ย้อนหลัง) BNDM ของ NR-grep ขยายเทคนิค BDM ด้วย Shift-Or bit-level parallelism [43]
มีทางเลือกทางทฤษฎีสองสามทางในการย้อนกลับสำหรับการอ้างอิงย้อนกลับและ "เลขชี้กำลัง" ของพวกเขาเป็นตัวช่วยที่เกี่ยวข้องกับจำนวนการอ้างอิงย้อนกลับซึ่งเป็นคุณสมบัติคงที่ของภาษา regexp บางภาษาเช่น POSIX วิธีการไร้เดียงสาวิธีหนึ่งที่ทำซ้ำ NFA ที่ไม่ย้อนกลับสำหรับบันทึกการอ้างอิงแต่ละรายการมีความซับซ้อนของ เวลาและ ช่องว่างสำหรับกองหญ้าที่มีความยาว n และ k backreferences ใน RegExp [44]งานทางทฤษฎีล่าสุดที่ใช้หน่วยความจำออโตมาตาให้ขอบเขตที่แน่นขึ้นตามโหนดตัวแปร "แอ็คทีฟ" ที่ใช้และความเป็นไปได้ของพหุนามสำหรับ regexps ที่อ้างถึงย้อนกลับบางส่วน [45]
Unicode
ในแง่ทฤษฎีชุดโทเค็นใด ๆ สามารถจับคู่โดยนิพจน์ทั่วไปได้ตราบเท่าที่มีการกำหนดไว้ล่วงหน้า ในแง่ของการใช้งานประวัติศาสตร์ regexes ถูกเขียนขึ้นมาเพื่อใช้ASCIIตัวอักษรเป็นชุดโทเค็นของพวกเขาแม้ว่าห้องสมุด regex ได้รับการสนับสนุนอื่น ๆ อีกมากมายชุดตัวอักษร หลายเครื่องยนต์ regex ทันสมัยมีอย่างน้อยการสนับสนุนบางส่วนสำหรับUnicode โดยส่วนใหญ่แล้วจะไม่แตกต่างกันว่าชุดอักขระคืออะไร แต่ปัญหาบางอย่างจะเกิดขึ้นเมื่อขยาย regexes เพื่อรองรับ Unicode
- การเข้ารหัสได้รับการสนับสนุน ไลบรารี regex บางแห่งคาดว่าจะทำงานกับการเข้ารหัสเฉพาะบางอย่างแทนที่จะใช้อักขระ Unicode ที่เป็นนามธรรม หลายเหล่านี้จำเป็นต้องใช้UTF-8เข้ารหัสขณะที่คนอื่นอาจคาดหวังUTF-16หรือUTF-32 ในทางตรงกันข้าม Perl และ Java ไม่เชื่อเรื่องพระเจ้าในการเข้ารหัสแทนที่จะดำเนินการกับอักขระที่ถอดรหัสภายใน
- ช่วงที่รองรับ Unicode เอ็นจิ้น regex จำนวนมากรองรับเฉพาะBasic Multilingual Planeนั่นคืออักขระที่เข้ารหัสได้เพียง 16 บิต ปัจจุบัน (ณ ปี 2559) มีเพียงเอนจิ้น regex เพียงไม่กี่ตัว (เช่น Perl และ Java) เท่านั้นที่สามารถรองรับช่วง Unicode แบบ 21 บิตเต็มรูปแบบได้
- ขยายโครงสร้าง ASCII ที่มุ่งเน้นการเป็น Unicode ตัวอย่างเช่นในการใช้งานแบบ ASCII ช่วงอักขระของแบบฟอร์ม
[x-y]
จะใช้ได้ทุกที่ที่xและyมีจุดรหัสอยู่ในช่วง [0x00,0x7F] และจุดรหัส ( x ) ≤ codepoint ( y ) ส่วนขยายตามธรรมชาติของช่วงอักขระดังกล่าวเป็น Unicode จะเปลี่ยนข้อกำหนดที่ให้ปลายทางอยู่ใน [0x00,0x7F] เป็นข้อกำหนดที่อยู่ใน [0x0000,0x10FFFF] อย่างไรก็ตามในทางปฏิบัติมักไม่เป็นเช่นนั้น การใช้งานบางอย่างเช่นgawkไม่อนุญาตให้ช่วงอักขระข้ามบล็อค Unicode ช่วงเช่น [0x61,0x7F] ถูกต้องเนื่องจากจุดสิ้นสุดทั้งสองอยู่ในบล็อกภาษาละตินพื้นฐานเช่นเดียวกับ [0x0530,0x0560] เนื่องจากจุดสิ้นสุดทั้งสองอยู่ในบล็อกอาร์เมเนีย แต่ช่วงเช่น [0x0061,0x0532] ไม่ถูกต้องเนื่องจากมี Unicode หลายบล็อก เอ็นจิ้นอื่น ๆ เช่นของตัวแก้ไขVimอนุญาตให้มีการข้ามบล็อก แต่ค่าอักขระต้องห่างกันไม่เกิน 256 [46] - กรณีที่ไม่รู้สึก แฟล็กความไม่ไวต่อตัวพิมพ์เล็กและตัวพิมพ์มีผลเฉพาะอักขระ ASCII แฟล็กอื่นมีผลต่ออักขระทั้งหมด เอ็นจิ้นบางตัวมีแฟล็กที่แตกต่างกันสองแฟล็กหนึ่งสำหรับ ASCII และอีกอันสำหรับ Unicode อักขระที่อยู่ในคลาส POSIX ก็แตกต่างกันไปเช่นกัน
- ญาติของคดีไม่รู้สึก เนื่องจาก ASCII มีความแตกต่างของกรณีความไม่ไวต่อตัวพิมพ์จึงกลายเป็นคุณลักษณะเชิงตรรกะในการค้นหาข้อความ Unicode แนะนำสคริปต์ตัวอักษรโดยไม่ต้องกรณีเช่นเทวนาครี สำหรับสิ่งเหล่านี้ความไวของตัวพิมพ์เล็กและใหญ่ไม่สามารถใช้ได้ สำหรับสคริปต์เช่นภาษาจีนความแตกต่างอีกประการหนึ่งดูเหมือนจะเป็นเหตุเป็นผล: ระหว่างแบบดั้งเดิมและแบบเรียบง่าย ในสคริปต์ภาษาอาหรับอาจต้องการความไม่ไวต่อตำแหน่งเริ่มต้นตรงกลางขั้นสุดท้ายและตำแหน่งที่แยกได้ ในภาษาญี่ปุ่นความไม่รู้สึกไวระหว่างฮิรางานะและคาตาคานะบางครั้งก็มีประโยชน์
- นอร์มัลไลเซชัน Unicode ได้รวมตัวละคร เช่นเดียวกับเครื่องพิมพ์ดีดรุ่นเก่าตัวอักษรธรรมดาสามารถตามด้วยสัญลักษณ์ที่ไม่มีการเว้นวรรคหนึ่งตัวขึ้นไป (โดยปกติจะเป็นตัวกำกับเสียงเช่นเครื่องหมายเน้นเสียง) เพื่อสร้างอักขระการพิมพ์เดี่ยว แต่ยังมีอักขระที่มีการผสมไว้ล่วงหน้าเช่นอักขระที่มีอักขระรวมกันตั้งแต่หนึ่งตัวขึ้นไป ลำดับของอักขระ + อักขระที่รวมกันควรจับคู่กับอักขระนำหน้าเดี่ยวที่เหมือนกัน กระบวนการสร้างมาตรฐานของลำดับอักขระ + การรวมอักขระเรียกว่าการทำให้เป็นมาตรฐาน
- รหัสควบคุมใหม่ Unicode นำมาใช้ในหมู่คนอื่น ๆเครื่องหมายลำดับไบต์และเครื่องหมายบอกทิศทางข้อความ รหัสเหล่านี้อาจต้องได้รับการจัดการด้วยวิธีพิเศษ
- ความรู้เบื้องต้นของการเรียนตัวอักษรสำหรับบล็อก Unicode สคริปต์และหลายคุณสมบัติตัวอักษรอื่น คุณสมบัติบล็อกมีประโยชน์น้อยกว่าคุณสมบัติของสคริปต์เนื่องจากบล็อกสามารถมีจุดรหัสจากสคริปต์ที่แตกต่างกันหลาย ๆ สคริปต์และสคริปต์สามารถมีจุดรหัสจากบล็อกที่แตกต่างกันได้ [47]ในPerlและ
java.util.regex
ไลบรารีคุณสมบัติของแบบฟอร์ม\p{InX}
หรือ\p{Block=X}
จับคู่อักขระในบล็อกXและ\P{InX}
หรือ\P{Block=X}
ตรงกับจุดรหัสที่ไม่อยู่ในบล็อกนั้น ในทำนองเดียวกัน\p{Armenian}
,\p{IsArmenian}
หรือ\p{Script=Armenian}
ตรงกับตัวอักษรใด ๆ ในสคริปต์อาร์เมเนีย โดยทั่วไป\p{X}
ตรงกับตัวอักษรใด ๆ กับทั้งคุณสมบัติไบนารีXหรือหมวดหมู่ทั่วไปX ตัวอย่างเช่น\p{Lu}
,\p{Uppercase_Letter}
หรือ\p{GC=Lu}
ตรงกับอักษรตัวพิมพ์ใหญ่ใด ๆ คุณสมบัติไบนารีที่มีไม่ประเภททั่วไป ได้แก่\p{White_Space}
,\p{Alphabetic}
, และ\p{Math}
\p{Dash}
ตัวอย่างของคุณสมบัติที่ไม่ใช่ไบนารี\p{Bidi_Class=Right_to_Left}
, และ\p{Word_Break=A_Letter}
\p{Numeric_Value=10}
ใช้
Regexes มีประโยชน์ในงานประมวลผลข้อความที่หลากหลายและโดยทั่วไปแล้วการประมวลผลสตริงโดยที่ข้อมูลไม่จำเป็นต้องเป็นข้อความ การใช้งานทั่วไปรวมถึงการตรวจสอบข้อมูล , ข้อมูลขูด (โดยเฉพาะเว็บขูด ), ข้อมูลการถกเถียงง่ายแยก , การผลิตของการเน้นไวยากรณ์ระบบและงานอื่น ๆ อีกมากมาย
แม้ว่า regexes จะมีประโยชน์ในเครื่องมือค้นหาทางอินเทอร์เน็ตแต่การประมวลผลทั่วทั้งฐานข้อมูลอาจใช้ทรัพยากรคอมพิวเตอร์มากเกินไปขึ้นอยู่กับความซับซ้อนและการออกแบบ regex แม้ว่าในหลาย ๆ กรณีผู้ดูแลระบบสามารถเรียกใช้การสืบค้นแบบ regex ภายในได้ แต่เครื่องมือค้นหาส่วนใหญ่ไม่ได้ให้การสนับสนุน regex แก่สาธารณะ ข้อยกเว้นเด่น ได้แก่การค้นหาของ Google รหัสและExalead อย่างไรก็ตาม Google Code Search ได้ปิดตัวลงในเดือนมกราคม 2555 [48]
ตัวอย่าง
กฎไวยากรณ์เฉพาะจะแตกต่างกันไปขึ้นอยู่กับการนำไปใช้งานภาษาโปรแกรมหรือไลบรารีที่ใช้งาน นอกจากนี้ฟังก์ชั่นการใช้งาน regex สามารถแตกต่างกันระหว่างรุ่น
เนื่องจากนิพจน์ทั่วไปอาจเป็นเรื่องยากที่จะอธิบายและทำความเข้าใจโดยไม่มีตัวอย่างเว็บไซต์เชิงโต้ตอบสำหรับการทดสอบนิพจน์ทั่วไปจึงเป็นแหล่งข้อมูลที่มีประโยชน์สำหรับการเรียนรู้นิพจน์ทั่วไปโดยการทดลอง ส่วนนี้ให้คำอธิบายพื้นฐานเกี่ยวกับคุณสมบัติบางประการของนิพจน์ทั่วไปโดยใช้ภาพประกอบ
ใช้อนุสัญญาต่อไปนี้ในตัวอย่าง [49]
metacharacter (s) ;; คอลัมน์ metacharacters ระบุไวยากรณ์ regex ที่กำลังแสดง= ~ ม // ;; บ่งชี้การดำเนินการจับคู่ regex ใน Perl= ~ s /// ;; บ่งชี้การดำเนินการแทนที่ regex ใน Perl
สิ่งที่น่าสังเกตก็คือ regexes เหล่านี้ล้วน แต่เป็นไวยากรณ์แบบ Perl นิพจน์ทั่วไปPOSIXมาตรฐานแตกต่างกัน
ตัวอย่างต่อไปนี้เป็นไปตามภาษาการเขียนโปรแกรมPerlรุ่น 5.8.8 31 มกราคม 2549 เว้นแต่จะระบุไว้เป็นอย่างอื่นซึ่งหมายความว่าการนำไปใช้งานอื่น ๆ อาจขาดการสนับสนุนบางส่วนของไวยากรณ์ที่แสดงไว้ที่นี่ (เช่นนิพจน์พื้นฐานเทียบกับนิพจน์ทั่วไป\( \)
เทียบกับนิพจน์ทั่วไป()
หรือขาด\d
แทนPOSIX [:digit:]
)
ไวยากรณ์และรูปแบบที่ใช้ในตัวอย่างเหล่านี้ตรงกับสภาพแวดล้อมการเขียนโปรแกรมอื่น ๆ เช่นกัน [50]
Metacharacter (s) | คำอธิบาย | ตัวอย่าง[51] |
---|---|---|
. | โดยปกติจะจับคู่อักขระใด ๆ ยกเว้นขึ้นบรรทัดใหม่ ภายในวงเล็บเหลี่ยมจุดเป็นตัวอักษร | $ string1 = "สวัสดีชาวโลก \ n" ; ถ้า ( $ string1 = ~ m /...../ ) { พิมพ์ "$ string1 มีความยาว> = 5. \ n" ; } เอาท์พุต: สวัสดีชาวโลก มีความยาว> = 5 |
( ) | จัดกลุ่มชุดขององค์ประกอบรูปแบบเป็นองค์ประกอบเดียว เมื่อคุณตรงกับรูปแบบในวงเล็บคุณสามารถใช้ใด ๆ ของ $1 , $2 ... หลังจากนั้นจะดูที่รูปแบบการจับคู่ก่อนหน้านี้ | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / (H .. ). (o .. ) / ) { พิมพ์ "เราจับคู่ '$ 1' และ '$ 2'. \ n" ; } เอาท์พุต: เราจับคู่ 'Hel' และ 'o W' |
+ | จับคู่องค์ประกอบรูปแบบก่อนหน้าอย่างน้อยหนึ่งครั้ง | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / l + / ) { พิมพ์ "มีตัวอักษรต่อเนื่อง \" l \ "อยู่ใน $ string1 อย่างน้อยหนึ่งตัว \ n" ; } เอาท์พุต: มีตัวอักษร "l" ติดกันอย่างน้อยหนึ่งตัวใน Hello World |
? | จับคู่องค์ประกอบรูปแบบก่อนหน้าเป็นศูนย์หรือครั้งเดียว | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / H.? e / ) { พิมพ์ "มี 'H' และ 'e' คั่นด้วย" ; พิมพ์ "0-1 ตัวอักษร (เช่น He Hue Hee) \ n" ; } เอาท์พุต: มี 'H' และ 'e' คั่นด้วยอักขระ 0-1 (เช่น He Hue Hee) |
? | ปรับเปลี่ยน* , + , ? หรือ{M,N} 'd regex ที่มาก่อนเพื่อให้ตรงเป็นไม่กี่ครั้งที่เป็นไปได้ | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / (l. +? o) / ) { พิมพ์ "การจับคู่แบบไม่โลภด้วย 'l' ตามด้วยหนึ่งหรือ" ; พิมพ์ "อักขระเพิ่มเติมคือ" llo "แทนที่จะเป็น" llo Wo "\ n" ; } เอาท์พุต: การจับคู่แบบไม่โลภด้วย "l" ตามด้วยอักขระอย่างน้อยหนึ่งตัวคือ "llo" แทนที่จะเป็น "llo Wo" |
* | จับคู่องค์ประกอบรูปแบบก่อนหน้าเป็นศูนย์หรือมากกว่าครั้ง | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / el * o / ) { พิมพ์ "มี 'e' ตามด้วยศูนย์ถึงหลาย" ; พิมพ์ "'l' ตามด้วย 'o' (เช่น eo, elo, ello, elllo) \ n" ; } เอาท์พุต: มี 'e' ตามด้วยศูนย์ถึงหลาย 'l' ตามด้วย 'o' (เช่น eo, elo, ello, elllo) |
{M,N} | หมายถึง M ต่ำสุดและจำนวนการจับคู่สูงสุด N N สามารถละเว้นและ M สามารถเป็น 0: {M} ตรงกับ "ตรง" ครั้ง M; {M,} ตรงกับ "อย่างน้อย" M ครั้ง; {0,N} ตรงกับ "มากที่สุด" N ครั้ง x* y+ z? จึงเทียบเท่ากับx{0,} y{1,} z{0,1} . | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / l {1,2} / ) { พิมพ์ "มีสตริงย่อยที่มีอย่างน้อย 1" ; พิมพ์ "และมากที่สุด 2 l ใน $ string1 \ n" ; } เอาท์พุต: มีสตริงย่อยที่มีอย่างน้อย 1 และไม่เกิน 2 l ใน Hello World |
[…] | หมายถึงชุดการจับคู่อักขระที่เป็นไปได้ | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / [aeiou] + / ) { พิมพ์ "$ string1 มีสระตั้งแต่หนึ่งตัวขึ้นไป \ n" ; } เอาท์พุต: สวัสดีชาวโลก มีสระอย่างน้อยหนึ่งเสียง |
| | แยกความเป็นไปได้อื่น ๆ | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / (สวัสดี | สวัสดี | Pogo) / ) { พิมพ์ "$ string1 มี Hello, Hi หรือ Pogo อย่างน้อยหนึ่งรายการ" ; } เอาท์พุต: สวัสดีชาวโลก มีสวัสดีสวัสดีหรือ Pogo อย่างน้อยหนึ่งรายการ |
\b | จับคู่ขอบเขตความกว้างเป็นศูนย์ระหว่างอักขระระดับคำ (ดูถัดไป) และอักขระคลาสที่ไม่ใช่คำหรือขอบ เหมือนกับ
| $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / llo \ b / ) { พิมพ์ "มีคำที่ลงท้ายด้วย 'llo'. \ n" ; } เอาท์พุต: มีคำที่ลงท้ายด้วย 'llo' |
\w | จับคู่อักขระที่เป็นตัวเลขและตัวอักษรรวมทั้ง "_"; เช่นเดียวกับ [A-Za-z0-9_] ใน ASCII และ
ใน Unicode [47]ซึ่ง | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / \ w / ) { พิมพ์ "มีตัวอักษรและตัวเลขอย่างน้อยหนึ่งตัว" ; พิมพ์ "อักขระใน $ string1 (AZ, az, 0-9, _) \ n" ; } เอาท์พุต: มีอักขระที่เป็นตัวเลขและตัวอักษรอย่างน้อยหนึ่งตัวใน Hello World (AZ, az, 0-9, _) |
\W | จับคู่อักขระที่ไม่ใช่ตัวเลขและตัวอักษรยกเว้น "_"; เช่นเดียวกับ [^A-Za-z0-9_] ใน ASCII และ
ใน Unicode | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / \ W / ) { พิมพ์ "ช่องว่างระหว่าง Hello และ" ; พิมพ์ "โลกไม่ใช่ตัวเลขและตัวอักษร \ n" ; } เอาท์พุต: ช่องว่างระหว่าง Hello และ World ไม่ใช่ตัวเลขและตัวอักษร |
\s | จับคู่อักขระช่องว่าง ซึ่งใน ASCII คือแท็บฟีดบรรทัดฟีดแบบฟอร์มการส่งคืนค่าขนส่งและช่องว่าง ใน Unicode ยังจับคู่ | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / \ s. * \ s / ) { พิมพ์ "ใน $ string1 มีอักขระเว้นวรรคสองตัวซึ่งอาจ" ; พิมพ์ "คั่นด้วยอักขระอื่น \ n" ; } เอาท์พุต: ใน Hello World มีอักขระช่องว่างสองอักขระซึ่งอาจคั่นด้วยอักขระอื่น |
\S | จับคู่อะไรก็ได้ยกเว้นช่องว่าง | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / \ S. * \ S / ) { พิมพ์ "ใน $ string1 มีอักขระที่ไม่ใช่ช่องว่าง 2 ตัวซึ่ง" ; พิมพ์ "อาจคั่นด้วยอักขระอื่น \ n" ; } เอาท์พุต: ใน Hello World มีอักขระที่ไม่ใช่ช่องว่างสองอักขระซึ่งอาจคั่นด้วยอักขระอื่น ๆ |
\d | จับคู่ตัวเลข เช่นเดียวกับ [0-9] ใน ASCII; ใน Unicode เช่นเดียวกับคุณสมบัติ \p{Digit} หรือ\p{GC=Decimal_Number} ซึ่งตัวเองเหมือนกับ\p{Numeric_Type=Decimal} คุณสมบัติ | $ string1 = "เบียร์ 99 ขวดบนผนัง" ; ถ้า ( $ string1 = ~ m / (\ d +) / ) { พิมพ์ "$ 1 เป็นตัวเลขแรกใน '$ string1' \ n" ; } เอาท์พุต: 99 เป็นหมายเลขแรกใน '99 ขวดเบียร์บนผนัง' |
\D | จับคู่ตัวเลขที่ไม่ใช่ตัวเลข เช่นเดียวกับ [^0-9] ใน ASCII หรือ\P{Digit} ใน Unicode | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / \ D / ) { พิมพ์ "มีอักขระอย่างน้อยหนึ่งตัวใน $ string1" ; พิมพ์ "ที่ไม่ใช่ตัวเลข \ n" ; } เอาท์พุต: มีอักขระอย่างน้อยหนึ่งตัวใน Hello World นั่นไม่ใช่ตัวเลข |
^ | ตรงกับจุดเริ่มต้นของบรรทัดหรือสตริง | $ string1 = "สวัสดีชาวโลก \ n" ; if ( $ string1 = ~ m / ^ He / ) { พิมพ์ "$ string1 ขึ้นต้นด้วยอักขระ" He ". \ n" ; } เอาท์พุต: สวัสดีชาวโลก เริ่มต้นด้วยตัวละคร 'เขา' |
$ | จับคู่ส่วนท้ายของบรรทัดหรือสตริง | $ string1 = "สวัสดีชาวโลก \ n" ; ถ้า ( $ string1 = ~ m / rld $ / ) { พิมพ์ "$ string1 เป็นบรรทัดหรือสตริง" ; พิมพ์ "ที่ลงท้ายด้วย" rld ". \ n" ; } เอาท์พุต: สวัสดีชาวโลก คือบรรทัดหรือสตริงที่ลงท้ายด้วย 'rld' |
\A | ตรงกับจุดเริ่มต้นของสตริง (แต่ไม่ใช่บรรทัดภายใน) | $ string1 = "สวัสดี \ nWorld \ n" ; ถ้า ( $ string1 = ~ m / \ AH / ) { พิมพ์ "$ string1 เป็นสตริง" ; พิมพ์ "ที่ขึ้นต้นด้วย" H "\ n" ; } เอาท์พุต: สวัสดีโลก คือสตริงที่ขึ้นต้นด้วย "H" |
\z | จับคู่ส่วนท้ายของสตริง (แต่ไม่ใช่บรรทัดภายใน) [52] | $ string1 = "สวัสดี \ nWorld \ n" ; ถ้า ( $ string1 = ~ m / d \ n \ z / ) { พิมพ์ "$ string1 เป็นสตริง" ; พิมพ์ "ที่ลงท้ายด้วย 'd \\ n'. \ n" ; } เอาท์พุต: สวัสดีโลก คือสตริงที่ลงท้ายด้วย "d \ n" |
[^…] | จับคู่อักขระทุกตัวยกเว้นอักขระที่อยู่ในวงเล็บ | $ string1 = "สวัสดีชาวโลก \ n" ; ถ้า ( $ string1 = ~ m / [^ abc] / ) { พิมพ์ "$ string1 มีอักขระอื่นที่ไม่ใช่" ; พิมพ์ "a, b และ c. \ n" ; } เอาท์พุต: สวัสดีชาวโลก มีอักขระอื่นที่ไม่ใช่ a, b และ c |
การเหนี่ยวนำ
มักจะสร้างนิพจน์ทั่วไปได้ ("induced" หรือ "learn") ตามชุดสตริงตัวอย่าง นี้เป็นที่รู้จักในฐานะผู้ชักนำของภาษาปกติและเป็นส่วนหนึ่งของปัญหาทั่วไปของการเหนี่ยวนำไวยากรณ์ในทฤษฎีการเรียนรู้คอมพิวเตอร์ อย่างเป็นทางการยกตัวอย่างของสตริงในภาษาปกติและบางทียังให้ตัวอย่างของสตริงที่ไม่ได้อยู่ในภาษาปกตินั้นเป็นไปได้ที่จะทำให้เกิดไวยากรณ์สำหรับภาษากล่าวคือนิพจน์ทั่วไปที่สร้างภาษานั้น ภาษาปกติบางภาษาไม่สามารถเกิดขึ้นได้ด้วยวิธีนี้ (ดูการระบุภาษาในขีด จำกัด ) แต่สามารถทำได้หลายภาษา ตัวอย่างเช่นชุดของตัวอย่าง {1, 10, 100} และชุดค่าลบ (ของตัวอย่างตัวอย่าง) {11, 1001, 101, 0} สามารถใช้เพื่อชักนำให้เกิดนิพจน์ทั่วไป1⋅0 * (1 ตามด้วยศูนย์หรือมากกว่า 0 วินาที)
ดูสิ่งนี้ด้วย
- การเปรียบเทียบเครื่องยนต์นิพจน์ทั่วไป
- แบบฟอร์ม Backus – Naur แบบขยาย
- การจับคู่อักขระตัวแทน
- ไวยากรณ์ของต้นไม้ปกติ
- โครงสร้างของทอมป์สัน - แปลงนิพจน์ทั่วไปให้เป็นหุ่นยนต์ จำกัด (NFA)
หมายเหตุ
- ^ Goyvaerts มกราคม"นิพจน์ปกติกวดวิชา - เรียนรู้วิธีการใช้นิพจน์ปกติ" www.regular-expressions.info . สืบค้นจากต้นฉบับเมื่อ 2016-11-01 . สืบค้นเมื่อ2016-10-31 .
- ^ Mitkov, Ruslan (2003). ฟอร์ดคู่มือของภาษาศาสตร์ สำนักพิมพ์มหาวิทยาลัยออกซ์ฟอร์ด น. 754. ISBN 978-0-19-927634-9. เก็บถาวรไปจากเดิมใน 2017/02/28 สืบค้นเมื่อ2016-07-25 .
- ^ Lawson, Mark V. (17 กันยายน 2546). ไฟไนต์ออโต CRC Press. หน้า 98–100 ISBN 978-1-58488-255-8. สืบค้นเมื่อ 27 กุมภาพันธ์ 2017 . สืบค้นเมื่อ25 กรกฎาคม 2559 .
- ^ Kleene 1951
- ^ Leung, Hing (16 กันยายน 2553). "ปกติภาษาและไฟไนต์ออโต" (PDF) มหาวิทยาลัยรัฐนิวเม็กซิโก สืบค้นจากต้นฉบับ (PDF)เมื่อ 5 ธันวาคม 2556 . สืบค้นเมื่อ13 สิงหาคม 2562 .
แนวคิดของเหตุการณ์ปกติได้รับการแนะนำโดย Kleene ผ่านคำจำกัดความของนิพจน์ทั่วไป
- ^ ข ธ อมป์สัน 1968
- ^ a b Johnson และคณะ พ.ศ. 2511 .
- ^ Kernighan, Brian (2007-08-08). "ปกตินิพจน์ Matcher" สวยรหัส O'Reilly สื่อ หน้า 1–2. ISBN 978-0-596-51004-6. เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2013-05-15 .
- ^ Ritchie, เดนนิสเอ็ม"เป็นประวัติศาสตร์ที่ไม่สมบูรณ์ของการแก้ไขข้อความ QED" สืบค้นจากต้นฉบับเมื่อ 1999-02-21 . สืบค้นเมื่อ9 ตุลาคม 2556 .
- ^ a b Aho & Ullman 1992 , 10.11 Bibliographic Notes for Chapter 10, p. 589.
- ^ Aycock 2003 , 2. JIT Compilation Techniques, 2.1 Genesis, p. 98.
- ^ Raymond, Eric S.อ้างถึงDennis Ritchie (2003) "อาชีพไฟล์ 4.4.7: grep" สืบค้นจากต้นฉบับเมื่อ 2011-06-05 . สืบค้นเมื่อ2009-02-17 .
- ^ "นิพจน์ปกติคุณสมบัติใหม่ใน Tcl 8.1" เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2013-10-11 .
- ^ "PostgreSQL 9.3.1 Documentation: 9.7. Pattern Matching" . เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2013-10-12 .
- ^ Wall, Larryและทีมพัฒนา Perl 5 (2006) "perlre: การแสดงออกปกติ Perl" สืบค้นจากต้นฉบับเมื่อ 2009-12-31 . สืบค้นเมื่อ2006-10-10 .
- ^ a b กำแพง (2545)
- ^ "GROVF | เร่ง Analytics ข้อมูลขนาดใหญ่" grovf.com . เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2019-10-22 .
- ^ "CUDA grep" bkase.github.io เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2019-10-22 .
- ^ a b c d grep (1) หน้า man
- ^ a b Hopcroft, Motwani & Ullman (2000)
- ^ Sipser (1998)
- ^ Gelade & เนเว่น (2008 , น. 332, Thm.4.1)
- ^ Gruber & Holzer (2008)
- ^ จาก Gelade & เนเว่น (2008) , การแสดงออกปกติของความยาวประมาณ 850 เช่นว่าส่วนประกอบของมันมีความยาวประมาณ 2 32สามารถพบได้ที่ไฟล์: RegexComplementBlowup.png
- ^ เจย์แอล. กิสเชอร์ (2527). (ไม่ทราบชื่อเรื่อง) (รายงานทางเทคนิค) มหาวิทยาลัยสแตนฟอร์ดฝ่ายคอมพ์ Sc.
- ^ จอห์นอีฮอปครอฟต์; Rajeev Motwani และ Jeffrey D. รู้เบื้องต้นเกี่ยวกับออทฤษฎีภาษาและการคำนวณ Upper Saddle River / NJ: แอดดิสันเวสลีย์ ISBN 978-0-201-44124-6.ที่นี่: Sect.3.4.6, p.117-120 - คุณสมบัตินี้ไม่จำเป็นต้องมีไว้สำหรับนิพจน์ทั่วไปแบบขยายแม้ว่าจะอธิบายคลาสที่ใหญ่กว่าภาษาทั่วไป cf. น. 121
- ^ Kozen (1991) [ ต้องการหน้า ]
- ^ วีเอ็นเรดโก (2507) "ในการกำหนดความสัมพันธ์สำหรับพีชคณิตของเหตุการณ์ปกติ" . Ukrainskii Matematicheskii Zhurnal 16 (1): 120–126. เก็บถาวรไปจากเดิมใน 2018/03/29 สืบค้นเมื่อ2018-03-28 . (เป็นภาษารัสเซีย)
- ^ ISO / IEC 9945-2: 1993เทคโนโลยีสารสนเทศ - อินเทอร์เฟซระบบปฏิบัติการพกพา (POSIX) - ส่วนที่ 2: เชลล์และยูทิลิตี้แก้ไขต่อเนื่องเป็น ISO / IEC 9945-2: 2002เทคโนโลยีสารสนเทศ - อินเทอร์เฟซระบบปฏิบัติการแบบพกพา (POSIX) - ส่วน 2: การเชื่อมต่อระบบ ISO / IEC 9945-2: 2003 และปัจจุบัน ISO / IEC / IEEE 9945: 2009เทคโนโลยีสารสนเทศ - ข้อมูลจำเพาะพื้นฐานของระบบปฏิบัติการแบบพกพา (POSIX®) ฉบับที่ 7
- ^ The Single Unix Specification (เวอร์ชัน 2)
- ^ ก ข "33.3.1.2 ชั้นเรียนตัวอักษร - Emacs คู่มือกระเพื่อม - รุ่น 25.1" gnu.org . 2016 ที่จัดเก็บจากเดิมใน 2020/10/07 สืบค้นเมื่อ2017-04-13 .
- ^ "Perl นิพจน์ปกติเอกสาร" perldoc.perl.org สืบค้นจากต้นฉบับเมื่อวันที่ 31 ธันวาคม 2552 . สืบค้นเมื่อ8 มกราคม 2555 .
- ^ ก ข "การแสดงออกไวยากรณ์ปกติ" Python 3.5.0 เอกสาร มูลนิธิซอฟต์แวร์หลาม สืบค้นจากต้นฉบับเมื่อวันที่ 18 กรกฎาคม 2018 . สืบค้นเมื่อ10 ตุลาคม 2558 .
- ^ ก ข "เรียน Essential: นิพจน์ปกติ: บ่งปริมาณ: ความแตกต่างในหมู่โลภไม่เต็มใจและเป็นเจ้าของบ่งปริมาณ" ชวาสอน คำพยากรณ์ ที่เก็บถาวรจากเดิมเมื่อวันที่ 7 ตุลาคม 2020 สืบค้นเมื่อ23 ธันวาคม 2559 .
- ^ “ การจัดกลุ่มอะตอม” . regex กวดวิชา ที่เก็บถาวรจากเดิมเมื่อวันที่ 7 ตุลาคม 2020 สืบค้นเมื่อ24 พฤศจิกายน 2562 .
- ^ Cezar Câmpeanu; Kai Salomaa & Sheng Yu (ธ.ค. 2546) "การศึกษานิพจน์ทั่วไปเชิงปฏิบัติอย่างเป็นทางการ" . International Journal of Foundations of Computer Science . 14 (6): 1007–1018 ดอย : 10.1142 / S012905410300214X . สืบค้นจากต้นฉบับเมื่อ 2015-07-04 . สืบค้นเมื่อ2015-07-03 . ทฤษฎีบท 3 (น. 9)
- ^ "Perl นิพจน์จับคู่เป็น NP-ยาก" perl.plover.com . เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2019-11-21 .
- ^ ตรรกะพเนจร "จะจำลอง lookaheads และ lookbehinds ในระบบอัตโนมัติแบบ จำกัด ได้อย่างไร" . วิทยาศาสตร์คอมพิวเตอร์ Stack แลกเปลี่ยน ที่เก็บถาวรจากเดิมเมื่อวันที่ 7 ตุลาคม 2020 สืบค้นเมื่อ24 พฤศจิกายน 2562 .
- ^ ค็อกซ์ (2550)
- ^ Laurikari (2009)
- ^ "gnulib / lib / dfa.c"
หากเครื่องสแกนตรวจพบการเปลี่ยนแปลงใน backref เครื่องจะส่งคืนค่า "กึ่งสำเร็จ" ซึ่งบ่งชี้ว่าการจับคู่จะต้องได้รับการตรวจสอบด้วยตัวจับคู่แบบย้อนกลับ
- ^ Kearns, Steven (สิงหาคม 2013). "Sublinear Matching กับ Finite Automata โดยใช้ Reverse Suffix Scanning" arXiv : 1308.3822 [ cs.DS ]
- ^ นาวาร์โรกอนซาโล (10 พฤศจิกายน 2544). "NR-grep: ได้อย่างรวดเร็วและมีความยืดหยุ่นเครื่องมือรูปแบบจับคู่" (PDF) ซอฟแวร์: การปฏิบัติและประสบการณ์ 31 (13): 1265–1312 ดอย : 10.1002 / spe.411 . S2CID 3175806 . เก็บถาวร (PDF)จากเดิมในวันที่ 7 ตุลาคม 2020 สืบค้นเมื่อ21 พฤศจิกายน 2562 .
- ^ "travisdowns / polyregex" 5 กรกฎาคม 2019 ที่จัดเก็บจากเดิมในวันที่ 14 กันยายน 2020 สืบค้นเมื่อ21 พฤศจิกายน 2562 .
- ^ Schmid, Markus L. (มีนาคม 2019). "นิพจน์ทั่วไปที่มีการอ้างอิงย้อนกลับ: เทคนิคการจับคู่พหุนาม - เวลา" arXiv : 1903.05896 [ cs.FL ]
- ^ "เอกสารเป็นกลุ่ม: รูปแบบ" . Vimdoc.sourceforge.net เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2013-09-25 .
- ^ ก ข "UTS # 18 Unicode นิพจน์ปกติภาคผนวก A: บล็อกตัวอักษร" เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2010-02-05 .
- ^ Horowitz, Bradley (24 ตุลาคม 2554). "การกวาดล้าง" . Google Blog สืบค้นเมื่อ 21 ตุลาคม 2018 . สืบค้นเมื่อ4 พฤษภาคม 2562 .
- ^ ไม่จำเป็นต้องใช้อักขระ "m" ในการระบุการดำเนินการจับคู่ Perlเสมอไป ตัวอย่างเช่น
m/[^abc]/
สามารถแสดงผลเป็น/[^abc]/
ไฟล์. ว่า 'ม' เป็นสิ่งจำเป็นเฉพาะในกรณีที่ผู้ใช้ต้องการเพื่อระบุการดำเนินการแข่งขันโดยไม่ต้องใช้คาดการณ์ล่วงหน้าเฉือนเป็น regexคั่น บางครั้งการระบุตัวคั่น regex ทางเลือกก็มีประโยชน์เพื่อหลีกเลี่ยง "การชนกันของตัวคั่น " ดู ' perldoc perlre Archived 2009-12-31 ที่ Wayback Machine ' สำหรับรายละเอียดเพิ่มเติม - ^ เช่นดู Java in a Nutshell , p. 213; การเขียนสคริปต์Pythonสำหรับวิทยาการคำนวณพี. 320; การเขียนโปรแกรม PHP , p. 106.
- ^ โปรดทราบว่าคำสั่ง if ทั้งหมดส่งคืนค่า TRUE
- ^ คอนเวย์เดเมียน (2548). "นิพจน์ปกติ, จุดสิ้นสุดของสตริง" Perl ปฏิบัติที่ดีที่สุด O'Reilly น. 240. ISBN 978-0-596-00173-5. เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2017-09-10 .
อ้างอิง
- Aho, Alfred V. (1990). van Leeuwen ม.ค. (เอ็ด) อัลกอริทึมสำหรับการค้นหาในรูปแบบสตริง คู่มือของทฤษฎีวิทยาศาสตร์คอมพิวเตอร์ปริมาณ A: อัลกอริทึมและความซับซ้อน สำนักพิมพ์ MIT หน้า 255–300
- อาโฮอัลเฟรดวี.; Ullman, Jeffrey D. (1992). "บทที่ 10 รูปแบบ, ออโตและนิพจน์ปกติ" (PDF) รากฐานของวิทยาศาสตร์คอมพิวเตอร์ เก็บถาวรไปจากเดิมใน 2020/10/07 สืบค้นเมื่อ2013-12-14 .
- "นิพจน์ทั่วไป" . เดี่ยวสเปก Unix, รุ่นที่ 2 กลุ่มเปิด ปี 1997 ที่จัดเก็บจากเดิมใน 2020/10/07 สืบค้นเมื่อ2011-12-13 .
- "บทที่ 9: นิพจน์ทั่วไป" . ข้อมูลจำเพาะเปิดฐานกลุ่ม กลุ่มเปิด (6) 2004. IEEE Std 1003.1, 2004 Edition เก็บถาวรไปจากเดิมใน 2011/12/02 สืบค้นเมื่อ2011-12-13 .
- ค็อกซ์รัส (2550). "นิพจน์ปกติการจับคู่ได้ง่ายและรวดเร็ว" สืบค้นจากต้นฉบับเมื่อ 2010-01-01 . สืบค้นเมื่อ2008-04-27 .
- ฟอร์ตาเบน (2004). Sams สอนตัวเองนิพจน์ปกติใน 10 นาที แซม ISBN 978-0-672-32566-3.
- ฟรีดล์, เจฟฟรีย์ EF (2002). การเรียนรู้นิพจน์ทั่วไป O'Reilly ISBN 978-0-596-00289-3. สืบค้นจากต้นฉบับเมื่อ 2005-08-30 . สืบค้นเมื่อ2005-04-26 .
- Gelade, Wouter; Neven, Frank (2008). ความชัดเจนของส่วนเติมเต็มและจุดตัดของนิพจน์ทั่วไป การดำเนินการของวันที่ 25 International Symposium ในด้านทฤษฎีวิทยาการคอมพิวเตอร์ (STACS 2008) หน้า 325–336 arXiv : 0802.2869 . สืบค้นจากต้นฉบับเมื่อ 2011-07-18 . สืบค้นเมื่อ2009-06-15 .
- Goyvaerts, ม.ค. ; เลวิธานสตีเวน (2552). ตำรานิพจน์ทั่วไป [O’illy]. ISBN 978-0-596-52068-7.
- กรูเบอร์เฮอร์มันน์; Holzer, Markus (2008). ไฟไนต์ออโต, เดี่ยวการเชื่อมต่อและการแสดงออกปกติขนาด (PDF) Proceedings of the 35th International Colloquium on Automata, Languages and Programming (ICALP 2008) . 5126 . หน้า 39–50 ดอย : 10.1007 / 978-3-540-70583-3_4 . เก็บถาวร (PDF)จากเดิม 2011/07/11 สืบค้นเมื่อ2011-02-03 .
- Habibi, Mehran (2004). โลกแห่งความจริงนิพจน์ปกติกับ Java 1.4 สปริงเกอร์. ISBN 978-1-59059-107-9.
- ฮอปครอฟต์, จอห์นอี.; Motwani, ราเยฟ; Ullman, Jeffrey D. (2000). บทนำสู่ทฤษฎีออโตมาตาภาษาและการคำนวณ (2nd ed.) แอดดิสัน - เวสลีย์.
- จอห์นสันวอลเตอร์แอล; พอร์เตอร์เจมส์เอช; แอ็คคลีย์สเตฟานีฉัน.; รอสส์ดักลาสที. (2511). "การสร้างตัวประมวลผลคำศัพท์ที่มีประสิทธิภาพโดยอัตโนมัติโดยใช้เทคนิคสภาวะ จำกัด " การติดต่อสื่อสารของพลอากาศเอก 11 (12): 805–813 ดอย : 10.1145 / 364175.364185 . S2CID 17253809
- คลีนสตีเฟนซี (2494). แชนนอนคลอดอี; McCarthy, John (eds.) เป็นตัวแทนของเหตุการณ์ในเส้นประสาทและตาข่าย จำกัด ออโต (PDF) ออศึกษา สำนักพิมพ์มหาวิทยาลัยพรินซ์ตัน หน้า 3–42 เก็บถาวร (PDF)จากเดิม 2020/10/07 สืบค้นเมื่อ2017-12-10 .
- Kozen, Dexter (1991). "ทฤษฎีบทที่สมบูรณ์สำหรับคลีนอัลเกบราสและพีชคณิตของเหตุการณ์ปกติ" [2534] Proceedings Sixth Annual IEEE Symposium on Logic in Computer Science . การดำเนินการของปีที่ 6 IEEE ประชุมวิชาการเกี่ยวกับลอจิกในสาขาวิทยาศาสตร์คอมพิวเตอร์ (สถานีจ่ายน้ำเย็น 1991) หน้า 214–225 ดอย : 10.1109 / LICS.1991.151646 . hdl : 1813/6963 . ISBN 978-0-8186-2230-4. S2CID 19875225
- ลอริการีวิลล์ (2552). "TRE ห้องสมุด 0.7.6" สืบค้นจากต้นฉบับเมื่อ 2010-07-14 . สืบค้นเมื่อ2009-04-01 .
- ไลเกอร์, ฟรองซัวส์; แม็คควีน, เครก; วิลตัน, พอล (2545). Visual Basic .NET ปรับแต่งข้อความคู่มือ Wrox กด ISBN 978-1-86100-730-8.
- ซิปเซอร์ไมเคิล (1998) "บทที่ 1: ภาษาปกติ" . รู้เบื้องต้นเกี่ยวกับทฤษฎีการคำนวณ สำนักพิมพ์ PWS. ได้ pp. 31-90 ISBN 978-0-534-94728-6.
- Stubblebine, Tony (2003). นิพจน์ปกติท่องเที่ยวอ้างอิง O'Reilly ISBN 978-0-596-00415-6.
- ทอมป์สันเคน (2511) "เทคนิคการเขียนโปรแกรม: อัลกอริทึมการค้นหานิพจน์ทั่วไป" การติดต่อสื่อสารของพลอากาศเอก 11 (6): 419–422 ดอย : 10.1145 / 363347.363387 . S2CID 21260384
- วอลล์แลร์รี่ (2545). "คติ 5: การจับคู่รูปแบบ" . สืบค้นจากต้นฉบับเมื่อ 2010-01-12 . สืบค้นเมื่อ2006-10-11 .
ลิงก์ภายนอก
สื่อที่เกี่ยวข้องกับRegexที่ Wikimedia Commons
- นิพจน์ทั่วไปที่Curlie
- ISO / IEC 9945-2: 1993 เทคโนโลยีสารสนเทศ - อินเทอร์เฟซระบบปฏิบัติการแบบพกพา (POSIX) - ส่วนที่ 2: เชลล์และยูทิลิตี้
- ISO / IEC 9945-2: 2002 เทคโนโลยีสารสนเทศ - อินเทอร์เฟซระบบปฏิบัติการแบบพกพา (POSIX) - ส่วนที่ 2: การเชื่อมต่อระบบ
- ISO / IEC 9945-2: 2003 เทคโนโลยีสารสนเทศ - อินเทอร์เฟซระบบปฏิบัติการแบบพกพา (POSIX) - ส่วนที่ 2: การเชื่อมต่อระบบ
- ISO / IEC / IEEE 9945: 2009 เทคโนโลยีสารสนเทศ - ข้อมูลจำเพาะพื้นฐานของระบบปฏิบัติการแบบพกพา (POSIX®) ฉบับที่ 7
- นิพจน์ทั่วไป, IEEE Std 1003.1-2017, Open Group