คำสั่งต่อไปนี้ใช้เพื่อค้นหาหมายเลขโทรศัพท์ 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
ไม่ได้พูดถึง
egrep
grep -E
สำหรับรุ่นอื่นที่ไม่ใช่ greu GNUgrep
อาจจะหรืออาจจะไม่ยอมรับ-E
ตัวเลือกและegrep
อาจเป็นโปรแกรมแยกต่างหาก