คำสั่งต่อไปนี้ใช้เพื่อค้นหาหมายเลขโทรศัพท์ 7 หลัก:
grep "[[:digit:]]\{3\}[ -]\?[[:digit:]]\{4\}" file
สิ่งที่\?ยืนหยัดเพื่อ?
คำสั่งต่อไปนี้ใช้เพื่อค้นหาหมายเลขโทรศัพท์ 7 หลัก:
grep "[[:digit:]]\{3\}[ -]\?[[:digit:]]\{4\}" file
สิ่งที่\?ยืนหยัดเพื่อ?
คำตอบ:
มันเหมือนกับเอ็น?จิ้นนิพจน์ทั่วไปอื่น ๆ อีกมากมายและหมายถึง "จับคู่ศูนย์หรือหนึ่งในสิ่งใด ๆ ที่เกิดขึ้นมาก่อน"
ในตัวอย่างของคุณ\?จะใช้กับ[ -], หมายถึงพยายามจับคู่ช่องว่างหรือเครื่องหมายลบ แต่ช่องว่างหรือเครื่องหมายลบเป็นตัวเลือก
ดังนั้นสิ่งเหล่านี้จะจับคู่:
555 1234
555-1234
5551234
เหตุผลที่เขียน\?แทนที่จะ?เป็นเพื่อความเข้ากันได้ย้อนหลัง
เวอร์ชันเดิมของการgrepใช้นิพจน์ทั่วไปชนิดต่าง ๆ เรียกว่า "นิพจน์ทั่วไปขั้นพื้นฐาน" ซึ่ง?หมายถึงเครื่องหมายคำถามตามตัวอักษร
เพื่อให้ grep ของ GNU สามารถมีค่าเป็นศูนย์หรือหนึ่งฟังก์ชันได้ แต่เพิ่มเข้าไป แต่ต้องใช้\?ไวยากรณ์เพื่อให้สคริปต์ที่ใช้?ยังคงทำงานได้ตามที่คาดไว้
โปรดทราบว่า grep มี-Eตัวเลือกที่ทำให้มันใช้ประเภทนิพจน์ทั่วไปที่ใช้กันทั่วไปมากกว่าที่เรียกว่า "นิพจน์ทั่วไปแบบขยาย"
man 1 grep:
-E, --extended-regexp
Interpret PATTERN as an extended regular expression
(ERE, see below). (-E is specified by POSIX.)
-G, --basic-regexp
Interpret PATTERN as a basic regular expression (BRE, see below).
This is the default.
...
Repetition
A regular expression may be followed by one of several repetition operators:
? The preceding item is optional and matched at most once.
...
grep understands three different versions of regular expression syntax:
“basic,” “extended” and “perl.”
...
Basic vs Extended Regular Expressions
In basic regular expressions the meta-characters ?, +, {, |, (, and )
lose their special meaning; instead use the backslashed versions
\?, \+, \{, \|, \(, and \).
ข้อมูลเพิ่มเติม:
grep -Eเป็นวิธี POSIX อย่างเป็นทางการ egrepถูกเลิกใช้ใน susv2 (1997) และลบออกใน susv3 (2001) จากข้อมูลจำเพาะ POSIX และ Unix
\?เป็น GNUism แม้ว่า
น่าเสียดายที่ไวยากรณ์ที่แน่นอนของนิพจน์ทั่วไปแตกต่างกันเล็กน้อยระหว่างโปรแกรมต่าง ๆ : grep regexes นั้นไม่เหมือนกับ sed regexes ซึ่งไม่เหมือนกับ emacs regexes ซึ่งไม่เหมือนกับ C ++ regexes อย่างแน่นอน บน. เพื่อให้เรื่องแย่ลงแม้แต่เครื่องมือ "มาตรฐาน" อย่าง grep อาจแตกต่างกันเล็กน้อยระหว่างระบบปฏิบัติการยูนิกซ์ที่แตกต่างกันเล็กน้อย
ใน regex อักขระบางตัวมีความหมายพิเศษ (เช่นวงเล็บเหลี่ยมในตัวอย่างของคุณ) และเปลี่ยนกลับไปเป็นความหมายปกติของพวกเขาเป็นตัวอักษรเมื่อคุณ "หลบหนี" พวกเขาโดยใส่เครื่องหมายแบ็กสแลชไว้ข้างหน้าพวกเขา เขียนเป็น \ [) คนอื่นทำงานในทางตรงกันข้ามและรับความหมายพิเศษเมื่อหนีออกมาเท่านั้น (เช่นธรรมดา n เป็นเพียงตัวอักษร แต่ \ n เป็นตัวดึงข้อมูลบรรทัด) และสิ่งเหล่านี้อีกครั้งสามารถแตกต่างกันระหว่างการใช้งาน regex
ในการใช้งาน regex ส่วนใหญ่เครื่องหมายคำถามหมายความว่ารายการก่อนหน้าเป็นทางเลือกในขณะที่เครื่องหมายคำถามแบบ Escape (\?) เป็นเครื่องหมายคำถามที่แท้จริง แต่ในอีกไม่กี่ภาษามันเป็นวิธีอื่น ตัวอย่างของคุณเข้าใจได้ทั้งสองทาง แต่ฉันคิดว่าคุณมีหนึ่งในภาษาถิ่นที่อยู่? เป็นตัวอักษรและ \? เป็นสัญลักษณ์เสริม ดังนั้น regex ของคุณอาจหมายถึง "สามหลักตามด้วยตัวเลือกเว้นวรรคหรือเส้นประตามด้วยตัวเลขสี่หลัก"
(เบาะแสอื่นสามารถเห็นได้ในโครงสร้างเช่น \ {3 \} ซึ่งมีความหมายชัดเจนว่าหมายถึง "3 จากรายการก่อนหน้านี้" อย่างชัดเจนในภาษาท้องถิ่นส่วนใหญ่ regex นี้จะเขียน {3} และ \ {จะเป็นวงเล็บที่แท้จริง .)
นี่เป็นข้อมูลสรุปโดยย่อที่มีอยู่แล้วในคำตอบอื่น ๆ
ในgrep, ?ตรงกับตัวอักษรเครื่องหมายคำถามตัวอักษรและ\?หมายถึงศูนย์หรือหนึ่งเกิดขึ้นของสิ่งที่นำหน้ามัน ดังนั้นในตัวอย่างในคำถามของคุณ[ -]\?จับคู่เว้นวรรคหรือยัติภังค์หรือไม่มีอะไรเลย
ในegrepหรือgrep -Eเป็นวิธีอื่น ๆ \?ตรงกับเครื่องหมายคำถามตามตัวอักษรและ?แสดงถึงศูนย์หรือหนึ่งเกิดขึ้น
สิ่งนี้ใช้กับ GNU grep; รายละเอียดสำหรับการใช้ grep ที่ไม่ใช่ของ GNU อาจแตกต่างกันเล็กน้อย โดยเฉพาะอย่างยิ่งgrepและegrepเป็นสองโปรแกรมที่แยกกันในอดีตและฉันไม่คิดว่าโปรแกรมตัวเก่าgrepจะมี-Eตัวเลือก POSIX ไม่ระบุgrep -Eแต่ (ฉันรู้สึกประหลาดใจที่จะค้นพบ) egrepไม่ได้พูดถึง
egrepgrep -Eสำหรับรุ่นอื่นที่ไม่ใช่ greu GNUgrepอาจจะหรืออาจจะไม่ยอมรับ-Eตัวเลือกและegrepอาจเป็นโปรแกรมแยกต่างหาก