grep และหนีเครื่องหมายดอลลาร์


31

$Id$ฉันต้องการที่จะทราบว่ามีไฟล์สตริง

grep \$Id\$  my_dir/mylist_of_files

ส่งกลับค่าที่เกิดขึ้น 0

ฉันค้นพบว่าฉันต้องใช้

grep \$Id$ my_dir/mylist_of_files

จากนั้นฉันจะเห็นว่า$Idมีสีในเอาต์พุตนั่นคือมันถูกจับคู่

ฉันจะจับคู่ที่สองได้อย่างไร$และทำไมไม่\$Id\$ทำงาน

ไม่สำคัญว่าตัวที่สอง$จะเป็นตัวละครตัวสุดท้ายหรือไม่

ฉันใช้grep2.9


ก่อนโพสต์คำถามของฉันฉันใช้ google ...

ฉันพบคำตอบ

หากต้องการค้นหา $ (เครื่องหมายดอลลาร์) ในไฟล์ชื่อ test2 ให้ป้อน:

grep \\ $ test2

จำเป็นต้องใช้อักขระ \\ (double backslash) เพื่อบังคับให้เชลล์ส่ง a \ $ (เครื่องหมายแบ็กสแลชเดี่ยว, เครื่องหมายดอลลาร์) ไปยังคำสั่ง grep อักขระ \ (แบ็กสแลชเดี่ยว) บอกให้คำสั่ง grep ปฏิบัติต่ออักขระต่อไปนี้ (ในตัวอย่างนี้ $) เป็นตัวอักษรมากกว่าอักขระนิพจน์ ใช้คำสั่ง fgrep เพื่อหลีกเลี่ยงความจำเป็นในการใช้อักขระเลี่ยงเช่นแบ็กสแลช

แต่ฉันไม่เข้าใจว่าgrep \$Idทำไมgrep \\$Id\\$มันถึงได้ผล

ฉันสับสนเล็กน้อย ...

คำตอบ:


25

มี 2 ​​ประเด็นแยกต่างหากที่นี่

  1. grepใช้นิพจน์ปกติพื้นฐาน (BRE) และ$เป็นอักขระพิเศษใน BRE เฉพาะตอนท้ายของนิพจน์ ผลลัพธ์ของสิ่งนี้คืออินสแตนซ์ของ$in ทั้งสอง$Id$นั้นไม่เท่ากัน ตัวแรกคือตัวอักษรปกติและตัวที่สองเป็นตัวยึดที่ตรงกับส่วนท้ายของบรรทัด เพื่อให้ที่สอง$การแข่งขันที่แท้จริงคุณจะต้องทับขวาหนีมันคือ$ $Id\$การหลบหนีสิ่งแรก$ก็ใช้ได้เช่นกัน: \$Id\$และฉันชอบสิ่งนี้มากกว่าเพราะมันดูสอดคล้องกันมากกว่า

  2. มีสองกลไกการหลบหนี / การอ้างถึงที่ไม่เกี่ยวข้องอย่างสมบูรณ์ในที่ทำงานที่นี่: การอ้างอิงเชลล์และการอ้างอิงเครื่องหมายแบ็กสแลชแบ็กสแลช ปัญหาคือตัวละครจำนวนมากที่นิพจน์ทั่วไปใช้นั้นมีความพิเศษต่อเชลล์เช่นกันและที่ด้านบนของแบ็กสแลชยกเว้น regex อักขระนั้นก็คืออักขระที่อยู่ในเชลล์ นี่คือสาเหตุที่คุณมักจะเห็นว่ามีการยุ่งเหยิงที่เกี่ยวข้องกับแบ็กสแลชสองครั้ง แต่ฉันไม่แนะนำให้ใช้แบ็กสแลชสำหรับเชลล์ที่อ้างถึงการแสดงออกปกติเพราะมันไม่สามารถอ่านได้มาก

    แต่วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการใส่ครั้งแรก regex 'regex'ทั้งหมดของคุณภายในราคาเดียวกับใน เครื่องหมายคำพูดเดี่ยวเป็นรูปแบบที่แข็งแกร่งที่สุดในการอ้างอิงเชลล์ได้ตราบใดที่ regex ของคุณไม่มีเครื่องหมายอัญประกาศเดี่ยวคุณไม่ต้องกังวลกับการอ้างเชลล์อีกต่อไปและสามารถมุ่งเน้นไปที่ไวยากรณ์ BRE บริสุทธิ์

ดังนั้นเมื่อนำสิ่งนี้กลับมาใช้กับตัวอย่างดั้งเดิมของคุณเราจะโยน regex ( \$Id\$) ที่ถูกต้องไว้ในเครื่องหมายคำพูดเดี่ยว ต่อไปนี้ควรทำสิ่งที่คุณต้องการ:

grep '\$Id\$' my_dir/my_file

เหตุผลที่\$Id\$ไม่ทำงานเป็นเพราะหลังจากการกำจัดเปลือกใบเสนอราคา (วิธีที่ถูกต้องมากขึ้นของการพูดเปลือก quoting) ถูกนำไปใช้ regex ที่เห็นคือgrep $Id$ตามที่อธิบายไว้ใน (1. ) regex นี้จับคู่กับตัวอักษร$Idที่ท้ายบรรทัดเท่านั้นเนื่องจากตัวแรก$เป็นตัวอักษรในขณะที่ตัวที่สองเป็นตัวยึดพิเศษ

¹โปรดทราบว่าหากคุณเปลี่ยนมาใช้ Extended Normal Expression (ERE) เช่นหากคุณตัดสินใจที่จะใช้egrep(หรือgrep -E) $ตัวละครจะมีความพิเศษอยู่เสมอ ใน ERE $Id$จะไม่มีวันจับคู่อะไรเลยเพราะคุณไม่มีตัวละครหลังจากสิ้นสุดบรรทัดดังนั้น\$Id\$จะเป็นวิธีเดียวที่จะไป


3
เพื่อหลีกเลี่ยงการตีความ grep พารามิเตอร์ที่ 1 grep -F '$Id$'ในฐานะการแสดงออกปกติคุณยังสามารถทำ
jfg956

ในเปลือกของฉัน (ทุบตี 4.3.42) grep '$Id\$' ...และgrep \$Id\\$ ...ทำงาน
nitsas

2
และถ้านี่คือคำสั่งใน makefile คุณต้องหลีกเลี่ยง$ด้วยคำสั่งก่อนหน้า$: grep '$$Id\$$'. stackoverflow.com/a/2382810/2097284
Camille Goudeseune

-2

วิธีค้นหา$Id$ไฟล์: คุณสามารถใช้:grep '\$id*' filename


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