นิพจน์ทั่วไปสำหรับค้นหาอักขระสองตัวใน Bash


10

ฉันกำลังมองหานิพจน์ทั่วไปที่ค้นหาการเกิดขึ้นของอักขระสองตัวในข้อความรายชื่อและอื่น ๆ บนบรรทัดคำสั่ง (Bash)

หลักคำถาม : มีวิธีง่ายๆในการมองหาลำดับเช่นaa, ll, tttttฯลฯ ที่หนึ่งกำหนดนิพจน์ปกติที่จะมองหาที่ปรากฏ n ของตัวละครเดียวกันด้วย? สิ่งที่ฉันกำลังมองหาคือการบรรลุเป้าหมายในระดับพื้นฐานมาก ๆ บนบรรทัดคำสั่ง ใน Linux Shell

หลังจากงานวิจัยบางอย่างฉันมาถึงคำตอบต่อไปนี้ - และคำถามที่เกิดจากพวกเขาดังนั้นพวกเขาเพียงแค่ให้คำแนะนำแก่ฉันว่าคำตอบอาจอยู่ที่ใด แต่:

ก) (e) grep และปัญหาแบ็กสแลช

  • grep 'a\{2\}' มองหา aa
  • egrep'a{2}' มองหา aa

คำถาม: ความจำเป็นของการตั้ง backlashes นั้นผูกพันกับคำสั่งที่ฉันใช้หรือไม่? ถ้าเป็นเช่นนั้นทุกคนสามารถให้คำแนะนำฉันกับฉันได้อย่างไรเมื่อใช้ (e) grep ที่นี่?

b) ฉันพบคำตอบนี้ที่นี่สำหรับคำถามของฉันแม้ว่าจะไม่ใช่สิ่งที่ฉันกำลังมองหา:

grep -E '(.)\1' filenameมองหารายการที่มีลักษณะเดียวกันที่ปรากฏมากกว่าหนึ่งครั้ง แต่ไม่ได้ถามบ่อยแค่ไหน ใกล้กับสิ่งที่ฉันกำลังมองหา แต่ฉันยังต้องการตั้งค่าการทำซ้ำจำนวนมาก

ฉันควรแยกคำถามนี้ออกเป็นสองคำถามหรือมากกว่านั้น แต่ฉันไม่ต้องการทำให้ไซต์ที่น่ากลัวนี้ท่วมท้น

PS: คำถามก็อาจจะปิดหัวข้อ แต่: มันin, inside, หรือat on the shellและon the command lineถูกต้องหรือไม่

คำตอบ:


8

นี่เป็นคำถามสองข้อและควรแยกกัน แต่เนื่องจากคำตอบนั้นค่อนข้างเรียบง่ายฉันจะวางมันไว้ที่นี่ คำตอบเหล่านี้มีไว้สำหรับ GNU grepโดยเฉพาะ

ก) เป็นเช่นเดียวกับegrep grep -Eทั้งสองระบุว่าควรใช้ "Extended Regular Expressions" แทนgrepนิพจน์ปกติที่เป็นค่าเริ่มต้น grepต้องใช้แบ็กสแลชสำหรับนิพจน์ธรรมดาธรรมดา

จากmanหน้า:

นิพจน์พื้นฐานกับ Extended Regular Expression

ในการแสดงออกปกติพื้นฐานเมตาอักขระ? , + , { , | , (และ)สูญเสียความหมายพิเศษของพวกเขา; ใช้แบ็กสแลชเวอร์ชัน\แทนแทน , \ + , \ { , \ | , \ (และ\)

ดูmanหน้าสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการประชุมทางประวัติศาสตร์และการพกพา

b) ใช้egrep '(.)\1{N}'และแทนที่Nด้วยจำนวนอักขระที่คุณต้องการแทนที่หนึ่ง (เนื่องจากจุดตรงกับอักขระแรก) egrep '(.)\1{3}'ดังนั้นหากคุณต้องการเพื่อให้ตรงกับตัวอักษรซ้ำสี่ครั้งการใช้งาน


เมื่ออ่าน man page ฉันต้องเข้าใจผิดหรือตีความส่วนที่คุณชี้ไปอย่างผิด ๆ เมื่อฉันทำงานผ่านแบบฝึกหัดการแสดงออกปกติบางอย่างไม่มีคำแนะนำของพฤติกรรมดังกล่าวที่คาดหวัง ฉันคิดว่า Regular Expression หมายถึงบางสิ่งในระดับพื้นฐานที่แอปพลิเคชันส่วนใหญ่ทำงานกับสัญลักษณ์ชุดเดียวกัน อีกครั้งฉันได้รับการพิสูจน์ว่าผิด ขอบคุณสำหรับความช่วยเหลือของคุณ! สิ่งนี้ช่วยฉันได้จริงๆ
erch

มันค่อนข้างสับสนในการอ่าน " ใช้แบ็กสแลชเสมอเพื่อใช้ความหมายพิเศษจากตัวละครเช่น., +, ฯลฯ " จากนั้นการค้นหาว่าสิ่งที่ดูเหมือนตรงข้ามคือกฎที่มีคำสั่งพื้นฐานที่สุด
erch

@ cellar.dweller มันสับสน! เหตุผลมากมายเป็นเรื่องเกี่ยวกับประวัติศาสตร์ ฉันคุ้นเคยกับรูปแบบ Extended มากขึ้นดังนั้นฉันจึงมักจะใช้เพียงแค่egrepถ้าฉันต้องการการแสดงออกปกติ (ตรงข้ามกับการจับคู่สตริงที่เรียบง่าย) ดังนั้นฉันจึงไม่ต้องกังวลเกี่ยวกับการจดจำความแตกต่างระหว่างgrepสอง ประเภทของการแสดงออกปกติ
depquid

4
โปรดทราบว่า ERE มาตรฐานไม่รองรับการอ้างอิงกลับในขณะที่ BRE มาตรฐานทำ ดังนั้นgrep '\(.\)\1\{3\}'มาตรฐานgrep -E '(.)\1{3}'คือไม่
Stéphane Chazelas

7

สิ่งนี้จะมองหาอักขระที่เหมือนกันตั้งแต่ 2 ตัวขึ้นไป:

grep -E '(.)\1+' file

หาก awk ของคุณมีตัวเลือก -o สิ่งนี้จะพิมพ์แต่ละคู่ที่บรรทัดใหม่ ..

grep -Eo '(.)\1+' file

หากต้องการค้นหาการแข่งขันที่มีการจับคู่ 3 รายการ:

grep -E '(.)\1{2}' file

หรือ 3 หรือมากกว่า:

grep -E '(.)\1{2,}' file

ฯลฯ ..


แก้ไข

จริง @stephane_chazelas ถูกต้องเกี่ยวกับการอ้างอิงกลับและ -E ฉันลืมเรื่องนั้นไป ฉันลองใช้ grep BSD และ grep GNU และใช้งานได้ แต่มันไม่ได้อยู่ใน greps อื่น ๆ คุณจะต้องใช้หนึ่งในรุ่นด้านล่าง ..

รุ่น grep ปกติ:

grep '\(.\)\1\{1,\}' file

grep -o '\(.\)\1\{1,\}' file

grep '\(.\)\1\{2\}' file

grep '\(.\)\1\{2,\}' file

-oตัวเลือกยังไม่ grep มาตรฐาน BTW (อาจถ้า grep ของคุณเข้าใจ -o ก็ยังสามารถทำอ้างอิงกลับ) ..


หมายเหตุ : grep -E '(.)\1{2,}'ไฟล์และgrep '\(.\)\1\{2\}'ไฟล์ไม่ถูกต้องตามที่ alexis ระบุและควรละเว้น ..


ขอบคุณมาก แต่: ฉันพูดถูกแล้วหากไม่มี-Eตัวเลือกgrepจะไม่ทำอะไรมาก? สิ่งนี้จะอธิบายได้ค่อนข้างมากตัวอย่างเช่นทำไมฉันจึงเสียเวลามากมายในการมองหาว่าฉันผิดตรงไหน!
erch

หากไม่มีตัวเลือก -E คุณสามารถทำเช่นเดียวกันในกรณีนี้ แต่คุณจะต้องหลบหนีมากกว่าและไม่มี+ผู้ให้บริการ .. ฉันจะโพสต์ตัวอย่างด้วย
Scrutinizer

การแก้ไขเล็ก ๆ : grep -E '(.)\1{2}'ไม่ว่า "ค้นหาการแข่งขันที่มี 3 การแข่งขันที่ตรงกัน" แม้ว่ามันจะตรงกับตัวละครที่เหมือนกันสามตัวพวกมันอาจจะฝังตัวในสตริงที่ยาวกว่า AAAAAเช่นมันจะตรงกับในสตริง 5 สัญลักษณ์ (และหากมีสัญลักษณ์ติดต่อกัน 6 รูปขึ้นไปมันจะจับคู่มากกว่าหนึ่งครั้ง)
alexis

ใช่คุณถูกต้องอย่างแน่นอนที่ไม่ได้ทำงานตามที่ตั้งใจในความเป็นจริงมันเป็นไปไม่ได้เช่นนั้น ..
Scrutinizer

3

ก่อนอื่นขอขอบคุณทุกท่านสำหรับความคิดเห็นและข้อเสนอแนะที่สนับสนุน มันกลับกลายเป็นว่าฉันค่อนข้างใกล้กับคำตอบแล้ว

ปัญหาหลักคือเกี่ยวกับ:

มีวิธีที่ง่ายที่จะมองหาnปรากฏของตัวละครเดียวกันเช่นaa,tttttt

คำตอบสั้น ๆ :

คำสั่ง [รูปแบบของ] ต่อไปนี้จะทำซ้ำaอย่างน้อยหนึ่งครั้งและไม่มีที่สิ้นสุด

grep 'a\{1,}

grep -E \(a\)\{1,\}

egrep a{1,}

หรือพร้อมกับนิพจน์ทั่วไปของ GNU grep a\+


จำนวนการทำซ้ำจะถูกตั้งค่าไว้ภายในวงเล็บปีกกาผ่านรูปแบบ{min,max}{n}ทำซ้ำทุกnครั้ง{n,}ทำซ้ำอย่างน้อยnครั้งและ{n,m}ทำซ้ำอย่างน้อยที่สุดnแต่ในmเวลาส่วนใหญ่

ดังนั้นจึงยกประเด็นรอง :

ความจำเป็นในการตั้งค่า backlashes ผูกพันกับคำสั่งที่ฉันใช้หรือไม่?

คำตอบสั้น ๆ : ใช่การใช้แบ็กสแลชขึ้นอยู่กับว่ามีใครใช้grepหรือegrep

  • grep: เครื่องหมายแบ็กสแลชเปิดใช้งานเมตาอักขระ [ใช้นิพจน์ปกติพื้นฐาน]
  • egrepbackslash ยกเลิกการใช้งานเมตาอักขระ [ใช้นิพจน์ทั่วไปเพิ่มเติม]

เช่นนี้เป็นคำตอบสั้น ๆ ผมต้องการที่จะให้ผู้ที่วิ่งเข้าไปในปัญหาเทียบเคียงฉันเพิ่มสรุปพื้นฐานของฉันของสิ่งหนึ่งที่ดูเหมือนจะต้องมีความตระหนักในการทำงานร่วมกับและgrepegrep




นิพจน์ปกติพื้นฐาน, ขยายและ GNU

นิพจน์ปกติพื้นฐาน

ที่ใช้ในการgrep, edและsedคำสั่ง

ฟีเจอร์การตั้งค่านิพจน์ปกติพื้นฐานคือ:

  • Metacharacters ส่วนใหญ่? [ . \ )ฯลฯ ถูกเปิดใช้งานผ่านแบ็กสแลช หากไม่มีเครื่องหมายแบ็กสแลชพวกเขาจะถูกใช้เป็นคำค้นหา (ส่วนหนึ่งของ)
  • ^ $ \<และ\>รองรับโดยไม่มีแบ็กสแลช
  • ไม่มีตัวอักษรย่อ [ \b, \sฯลฯ ]

การแสดงออกปกติของGNUพื้นฐานจะเพิ่มเข้าไป

  • \?ทำซ้ำอักขระศูนย์หรือหนึ่งครั้ง ( c\?ตรงกันcและcc) และเป็นทางเลือกสำหรับ\{0,1\}
  • \+ทำซ้ำตัวอักษรอย่างน้อยหนึ่งครั้ง ( c\+แมตช์cc, ccccccccฯลฯ ) และเป็นทางเลือกสำหรับ\{1,\}

  • \|ได้รับการสนับสนุน (เช่นgrep a\|bจะค้นหาaหรือb

grep -E เปิดใช้งานคำสั่งเพื่อใช้ทั้งชุดของ Extended Regular Expression:


นิพจน์ปกติเพิ่มเติม [ERE]

ที่ใช้ในการegrep, awkและemacsเป็นชุดพื้นฐานพร้อมคุณสมบัติค่อนข้างบาง

  • อักขระเมตาถูกปิดใช้งานผ่านแบ็กสแลช
  • ไม่มีการอ้างอิงกลับ
  • อื่น: เวทมนตร์ปกติจำนวนมากนิพจน์ปกติสามารถทำเพื่อ

GNUขยายนิพจน์ปกติ

เพิ่มคุณสมบัติดังต่อไปนี้

ลิงค์ทั้งสองจะตรงไปที่ express-expressions.info ซึ่งนอกจากการสนับสนุนที่ยอดเยี่ยมฉันได้มาที่นี่จริงๆช่วยฉันได้มาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.