วิธีทำให้ grep จับคู่เฉพาะเมื่อทั้งบรรทัดตรงกัน?


104

ฉันมีสิ่งเหล่านี้:

$ cat a.tmp
ABB.log
ABB.log.122
ABB.log.123

ฉันต้องการหา ABB.log ที่ตรงกันทุกประการ

แต่เมื่อฉันทำ

$ grep -w ABB.log a.tmp
ABB.log
ABB.log.122
ABB.log.123

มันแสดงให้เห็นทั้งหมด

ได้สิ่งที่ต้องการโดยใช้ grep หรือไม่?

คำตอบ:


105

เพียงระบุจุดยึด regexp

grep '^ABB\.log$' a.tmp

2
จำเป็นต้องใช้พุกทั้งสอง (^ และ $)
user562374

2
ทำได้ดีนี่! และถ้าฉันใช้ regex สำหรับการจับคู่จากไฟล์? "grep -f รูปแบบ a.tmp" ??
สีเขียว 69

@ green69 หลายปีที่ผ่านมา แต่คุณสามารถใช้ sed เพื่อเพิ่มจุดยึดก่อนที่จะส่งรูปแบบไปยัง grep:sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
Randoms

155
grep -Fx ABB.log a.tmp

จากหน้า grep man:

-F, --fixed-strings
ตีความรูปแบบเป็น (รายการ) สตริงคงที่
-x, --line-regexp
เลือกเฉพาะการจับคู่ที่ตรงกับบรรทัดทั้งหมด


2
ไม่สามารถใช้ -F ได้อย่างน่าเสียดาย
Johnyy

@Johnyy ไม่-F? คุณอยู่ที่ Solaris หรือเปล่า? ถ้าเป็นเช่นนั้นให้ใช้/usr/xpg4/bin/grep
Scrutinizer

9
ฉันใช้grepภายในสคริปต์ทุบตีและตัวเลือกนี้ดีกว่าใช้นิพจน์ทั่วไปตามที่แนะนำในคำตอบที่ยอมรับ เนื่องจากฉันมีอักขระพิเศษบางตัวในตัวแปรที่ฉันกำลังค้นหา (เช่น.) และฉันไม่จำเป็นต้องหลบหนีเมื่อใช้คำสั่ง
Gustavo Straube

1
คำตอบที่ดีที่สุด IMO เพราะอนุญาตให้ใช้อักขระพิเศษโดยไม่ต้องหลบหนี
แก้ไขเมื่อ

1
สิ่งนี้ดีกว่าเพราะทำงานกับตัวแปรได้ด้วย
ybenjira

23

นี่คือสิ่งที่ฉันทำแม้ว่าการใช้แองเคอจะเป็นวิธีที่ดีที่สุด:

grep -w "ABB.log " a.tmp

เช่นนี้.. มันจะกลับมาจับคู่บรรทัดแรก
user765443

1
สิ่งนี้ต้องใช้ช่องว่างหลังจากABB.logนั้นซึ่งไม่ใช่กรณีทั่วไปกล่าวคือมันจะล้มเหลวเกือบตลอดเวลา
Jahid

3

คำแนะนำส่วนใหญ่จะล้มเหลวหากมีช่องว่างนำหน้าหรือต่อท้ายมากพอ ๆ กันซึ่งจะมีความสำคัญหากไฟล์ถูกแก้ไขด้วยมือ สิ่งนี้จะทำให้อ่อนแอน้อยลงในกรณีนั้น:

grep '^[[:blank:]]*ABB\.log[[:blank:]]*$' a.tmp

ลูปในขณะอ่านอย่างง่ายในเชลล์จะทำสิ่งนี้โดยปริยาย:

while read file
do 
  case $file in
    (ABB.log) printf "%s\n" "$file"
  esac
done < a.tmp


1

ฉันตั้งใจจะเพิ่มคำอธิบายเพิ่มเติมเกี่ยวกับความพยายามของ OP และคำตอบอื่น ๆ ด้วย

คุณสามารถใช้โซลูชันของ John Kugelmansเช่นนี้ได้เช่นกัน:

grep -x "ABB\.log" a.tmp

การอ้างถึงสตริงและการหลีกเลี่ยงจุด ( .) ทำให้ไม่ต้องการ-Fแฟล็กอีกต่อไป

คุณต้องหลีกเลี่ยง.(จุด) (เนื่องจากตรงกับอักขระใด ๆ (ไม่เพียง แต่.) หากไม่ใช้ Escape) หรือใช้-Fแฟล็กกับ grep -Fแฟล็กทำให้เป็นสตริงคงที่ (ไม่ใช่นิพจน์ทั่วไป)

หากคุณไม่อ้างถึงสตริงคุณอาจต้องใช้แบ็กสแลชคู่เพื่อหลีกเลี่ยงจุด ( .):

grep -x ABB\\.log a.tmp


ทดสอบ:

$ echo "ABBElog"|grep -x  ABB.log
ABBElog #matched !!!
$ echo "ABBElog"|grep -x  "ABB\.log"
#returns empty string, no match


บันทึก:

  1. -x บังคับให้ตรงกันทั้งเส้น
  2. คำตอบที่ใช้ non Escape .โดยไม่มี-Fแฟล็กนั้นผิด
  3. คุณสามารถหลีกเลี่ยง-xสวิทช์โดยการตัดสตริงรูปแบบของคุณด้วยและ^ $ในกรณีนี้ทำให้แน่ใจว่าคุณไม่ได้ใช้-Fแทนหลบหนี.เพราะ-Fจะป้องกันการตีความ regex ของและ^$


แก้ไข: (เพิ่มคำอธิบายเพิ่มเติมเกี่ยวกับ @hakre):

หากคุณต้องการจับคู่สตริงที่ขึ้นต้นด้วย-คุณควรใช้--กับ grep สิ่งที่ตามมา--จะถูกนำมาเป็นอินพุต (ไม่ใช่ตัวเลือก)

ตัวอย่าง:

echo -f |grep -- "-f"     # where grep "-f" will show error
echo -f |grep -F -- "-f"  # whre grep -F "-f" will show error
grep "pat" -- "-file"     # grep "pat" "-file" won't work. -file is the filename

คุณเคยพบว่า -F หายไปในกรณีของคุณหรือไม่? ถ้าเป็นเช่นนั้นคุณช่วยบอกได้ไหมว่าเป็นกรณีใด
hakre

@hakre คุณอ่านคำตอบของฉันครบถ้วนหรือยัง? ฉันอธิบาย (ค่อนข้างชัดเจน) ว่าทำไม-Fไม่จำเป็นถ้า.มีการหลบหนีอย่างถูกต้อง
Jahid

แน่นอน แน่นอนฉันแค่ถามว่า: -Fว่างเมื่อคุณเขียนสิ่งนี้หรือไม่? ถ้าไม่คุณใช้ระบบใด ฉันไม่พบข้อมูลดังกล่าวในคำตอบของคุณซึ่งตอนนี้ก็ยังเป็นเช่นนั้นเมื่อฉันอ่านซ้ำอีกครั้ง แน่ใจจริงๆฉันอ่านคำตอบของคุณทั้งหมดอย่างน้อยสองครั้ง ;)
hakre

@hakre แน่นอน-Fสามารถใช้ได้ (ฉันพูดว่า: "หรือใช้-Fธงกับgrep")
Jahid

ขอบคุณสำหรับข้อมูลเชิงลึก ยังคงมีคำถามเพียงข้อเดียว: ถ้า-Fเป็นคำตอบทำไมต้องกังวลกับการหนี คุณมีความคิดเห็นอย่างไรเกี่ยวกับเรื่องนี้?
hakre


-1
    $ cat venky
    ABB.log
    ABB.log.122
    ABB.log.123

    $ cat venky | grep "ABB.log" | grep -v "ABB.log\."
    ABB.log
    $

    $ cat venky | grep "ABB.log.122" | grep -v "ABB.log.122\."
    ABB.log.122
    $

1
การดำเนินการนี้จะจับคู่ไฟล์ที่ลงท้ายด้วย ABB.log ด้วยและจุดควรจะใช้ Escape
Scrutinizer

-1

เหมาะสำหรับฉัน :

grep "\bsearch_word\b" text_file > output.txt  

\b ระบุ / กำหนดขอบเขต

ดูเหมือนว่าจะทำงานได้ค่อนข้างเร็ว


นอกจากนี้ยังจับคู่บรรทัดใด ๆ ที่มีการsearch_wordคั่นด้วยขอบเขตของคำ ตัวอย่างเช่นจะจับคู่บรรทัด "foo search_word bar"
Rohan Singh

-2

ใช้กับ HPUX หากเนื้อหาของไฟล์มีช่องว่างระหว่างคำให้ใช้สิ่งนี้:

egrep "[[:space:]]ABC\.log[[:space:]]" a.tmp


OP ต้องการจับคู่ทั้งบรรทัดไม่ใช่คำที่คั่นด้วยช่องว่างภายในบรรทัด
Keith Thompson


-3

ฉันต้องการคุณสมบัตินี้ แต่ก็ต้องการให้แน่ใจว่าฉันไม่ได้ส่งคืนบรรทัดที่มีคำนำหน้าก่อน ABB.log:

  • ABB.log
  • ABB.log.122
  • ABB.log.123
  • 123ABB.log

grep "\WABB.log$" -w a.tmp

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