ใช้เครื่องหมายดาวใน grep


90

ฉันพยายามค้นหาสตริงย่อย "abc" ในไฟล์เฉพาะใน linux / bash

ดังนั้นฉันจึง:

grep '*abc*' myFile

มันกลับไม่มีอะไร

แต่ถ้าฉันทำ:

grep 'abc' myFile

ส่งคืนการจับคู่อย่างถูกต้อง

ตอนนี้นี่ไม่ใช่ปัญหาสำหรับฉัน แต่ถ้าฉันต้องการ grep สำหรับสตริงที่ซับซ้อนกว่านี้ให้พูดว่า

*abc * def *

ฉันจะทำมันให้สำเร็จโดยใช้ grep ได้อย่างไร


3
grep เองไม่รองรับสัญลักษณ์แทนบนแพลตฟอร์มส่วนใหญ่ คุณต้องใช้ egrep เพื่อใช้สัญลักษณ์แทน เชลล์มีไวยากรณ์ที่แตกต่างกัน "*" ในเชลล์คือ <any string> ใน egrep เป็นโอเปอเรเตอร์ที่ระบุว่า "0 to many of the previous entity" ใน grep มันเป็นเพียงตัวละครปกติ
PanCrit

@ PanCrit: *หมายถึงสิ่งเดียวกันใน grep และ egrep: เป็นตัวบอกปริมาณที่หมายถึงอะตอมก่อนหน้าเป็นศูนย์หรือมากกว่า นั่นเป็นแนวคิดที่แตกต่างอย่างสิ้นเชิงกับสัญลักษณ์แทนที่เชลล์ใช้
Alan Moore

คำตอบ:


124

เครื่องหมายดอกจันเป็นเพียงตัวดำเนินการซ้ำแต่คุณต้องบอกสิ่งที่คุณทำซ้ำ /*abc*/จับคู่สตริงที่มี ab และศูนย์หรือมากกว่า c (เพราะตัวที่สอง * อยู่บน c ตัวแรกไม่มีความหมายเพราะไม่มีอะไรให้มันซ้ำ) หากคุณต้องการจับคู่สิ่งใดคุณต้องพูด.*- จุดหมายถึงอักขระใด ๆ ( ตามหลักเกณฑ์บางประการ ) หากคุณต้องการเพียงแค่ตรงกับ abc grep 'abc' myFileคุณก็อาจจะบอกว่า สำหรับการจับคู่ที่ซับซ้อนยิ่งขึ้นคุณต้องใช้.*- grep 'abc.*def' myFileจะจับคู่สตริงที่มี abc ตามด้วย def กับบางสิ่งที่เลือกได้

อัปเดตตามความคิดเห็น:

*ในนิพจน์ทั่วไปไม่เหมือนกับ * ในคอนโซลทุกประการ ในคอนโซล * เป็นส่วนหนึ่งของโครงสร้างglobและทำหน้าที่เป็นตัวแทน (เช่นls *.logจะแสดงรายการไฟล์ทั้งหมดที่ลงท้ายด้วย. log) อย่างไรก็ตามในนิพจน์ทั่วไป * เป็นโมดิฟายเออร์ซึ่งหมายความว่าจะใช้กับอักขระหรือกลุ่มที่อยู่ข้างหน้าเท่านั้น หากคุณต้องการให้ * ในนิพจน์ทั่วไปทำหน้าที่เป็นตัวแทนคุณต้องใช้.*ตามที่กล่าวไว้ก่อนหน้านี้ - จุดเป็นอักขระตัวแทนและดาวเมื่อแก้ไขจุดหมายถึงค้นหาจุดหนึ่งจุดขึ้นไป กล่าวคือ. ค้นหาอักขระใดตัวหนึ่งหรือหลายตัว


1
ฉันคิดว่าผู้ถามสับสนเกี่ยวกับความแตกต่างระหว่างสัญลักษณ์แทนเชลล์และนิพจน์ทั่วไป ฉันยังสงสัยว่านิพจน์ที่ซับซ้อนกว่านั้นจะเป็น: grep 'abc. * def' (มีช่องว่างอย่างน้อยหนึ่งช่อง - อาจเป็นสองตามที่ฉันเขียน)
Jonathan Leffler

1
ที่จริงผู้ถามดูเหมือนจะไม่เข้าใจว่า 'abc' ไม่ใช่สิ่งเดียวกับ '^ abc $' :-D
Massa

1
ใช่ฉันสับสนระหว่าง glob และนิพจน์ทั่วไปแบบเต็ม ฉันใช้ * โดยไม่มีจุดเพื่อหมายถึงการจับคู่สิ่งใด ๆ บนเชลล์
Saobi

1
grep *หมายถึง "0 หรือมากกว่า" และ grep เป็นค่าเริ่มต้น ทราบว่าใน grep พื้นฐานการแสดงออกปกติ metacharacters ?, +, {, |, (และ )สูญเสียความหมายพิเศษของพวกเขา ข้อมูลเพิ่มเติม: grep regexps
KrisWebDev

25

อักขระจุดหมายถึงการจับคู่อักขระใด ๆ ดังนั้น.*หมายถึงการเกิดขึ้นของอักขระใด ๆ เป็นศูนย์หรือมากกว่า คุณอาจจะหมายถึงการใช้มากกว่าแค่.**


Dot เป็นตัวละครที่เมตาที่รับตัวอักษรใด ๆ ยกเว้นสายใหม่
Abhishek Kamal

12

"สัญลักษณ์รูปดาว" มีความหมายก็ต่อเมื่อมีบางสิ่งอยู่ข้างหน้า หากไม่มีเครื่องมือ (grep ในกรณีนี้) อาจถือว่าเป็นข้อผิดพลาด ตัวอย่างเช่น:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz

5
* ไม่ได้ไร้ความหมาย; มันไม่ได้มีความหมายตามปกติ (ซ้ำซาก) แต่หมายถึง "ฉันเป็นดารา" มันจะจับคู่บรรทัดที่มีดาวตามด้วย x, y และ z
Jonathan Leffler

2
@ โจนาธานมันขึ้นอยู่กับเครื่องมือ

9

ใช้ grep -P - ซึ่งเปิดใช้งานการสนับสนุนสำหรับนิพจน์ทั่วไปสไตล์ Perl

grep -P "abc.*def" myfile

6

นิพจน์ที่คุณพยายามเช่นเดียวกับที่ทำงานบนบรรทัดคำสั่งเชลล์ใน Linux เช่นเรียกว่า " glob " นิพจน์ Glob ไม่เต็มนิพจน์ทั่วไปซึ่งเป็นสิ่งที่ grep ใช้เพื่อระบุสตริงที่ต้องการค้นหา นี่คือโพสต์ (เก่าเล็ก) เกี่ยวกับความแตกต่าง นิพจน์ glob (เช่นใน "ls *") ถูกตีความโดยเชลล์เอง

เป็นไปได้ที่จะแปลจาก globs เป็น REs แต่โดยทั่วไปคุณต้องทำในหัวของคุณ


1
มันเป็นเพียงลูกโลกถ้ามันถูกแยกวิเคราะห์โดยเปลือก เนื่องจากเขาเก็บรักษาสตริงการค้นหาไว้ในเครื่องหมายคำพูดเดี่ยวเชลล์จึงปล่อยสตริงไว้เพียงอย่างเดียวและส่งต่อให้เหมือนเดิมใน argv ถึง grep
คอมไพเลอร์เด่น

4

คุณไม่ได้ใช้นิพจน์ทั่วไปดังนั้นควรเลือกตัวแปร grep fgrepซึ่งจะทำงานตามที่คุณคาดหวัง


2
fgrepเลิกใช้งานแล้วgrep -fควรใช้แทน
Prometheus

1
นั่นคือ "grep -F" fgrep ที่ดีอาจ "เลิกใช้แล้ว" แต่จะไม่นำไปใช้ในขณะที่ฉันยังมีชีวิตอยู่
Andrew Beals


1

นี่อาจเป็นคำตอบที่คุณกำลังมองหา:

grep abc MyFile | grep def

สิ่งเดียวคือ ... มันจะออกบรรทัดเป็น "def" อยู่ก่อนหรือหลัง "abc"


1

สิ่งนี้ใช้ได้ผลสำหรับฉัน:

grep ". * $ {expr}" - มีเครื่องหมายคำพูดคู่นำหน้าด้วยจุด โดยที่ "expr" คือสตริงที่คุณต้องการในตอนท้ายของบรรทัด

มาตรฐาน unix grep ที่ไม่มีสวิตช์เพิ่มเติม


0

'*' ทำงานเป็นตัวปรับแต่งสำหรับรายการก่อนหน้า ดังนั้น "abc * def" จะค้นหา "ab" ตามด้วย 0 หรือมากกว่า "c ตามด้วย" def "

สิ่งที่คุณอาจต้องการคือ "abc. * def" ซึ่งค้นหา "abc" ตามด้วยอักขระจำนวนเท่าใดก็ได้ตามด้วย "def"

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