จะค้นหาข้อความในไฟล์โดยไม่สนใจบรรทัดใหม่ได้อย่างไร


11

ฉันต้องการค้นหาข้อความที่อาจแบ่งออกเป็นหลายบรรทัดในไฟล์ grep ที่จะละเว้นการแบ่งบรรทัดและส่งคืนช่วงการจับคู่ของบรรทัด

เช่นฉันจะค้นหาis an example fileและคาดหวังว่าจะพบได้ในไฟล์ต่อไปนี้:

นี่คือ ไฟล์ตัวอย่าง

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


ทางออกที่ไม่เหมาะอย่างหนึ่งคือtr '\n' ' ' | grepการจำแนกระหว่างการจับคู่และการจับคู่ที่ไม่ตรงกัน แต่ไม่แสดงการจับคู่หรือจัดการกับไฟล์ขนาดใหญ่ได้ดี


บน SO (ไม่มีคำตอบที่ชัดเจน): stackoverflow.com/q/1858312/1449460
Nikana Reklawyks

ในฐานะที่เป็นบันทึกด้านการค้นหา emacs 'ดูเหมือนว่าจะทำงาน ( isearch-forward)
Nikana Reklawyks

/This\_sisดังนั้นกลุ่มของ: สำหรับรายละเอียดเพิ่มเติม: :help \_s.
lcd047

เพิ่มบรรทัดนี้ที่ท้ายบรรทัดค้นหาของคุณ: tr -n "\ n" สิ่งนี้จะลบบรรทัดใหม่ทั้งหมด หวังว่าจะช่วยได้!
Dan Howel

คำตอบ:


12

GNU grepสามารถทำได้

grep -z 'is\san\sexample\sfile.' file

ในการเติมเต็มบางประเด็นที่เกิดขึ้นในความคิดเห็นมีการดัดแปลงสคริปต์:

 grep -oz '^[^\n]*\bis\s*an\s*example\s*file\.[^\n]*' file

เกี่ยวกับไฟล์ขนาดใหญ่ฉันไม่มีจินตนาการเรื่องการ จำกัด หน่วยความจำ แต่ในกรณีที่เกิดปัญหาคุณสามารถใช้งานได้ฟรี sed

sed '/\bis\b/{
          :1
          N
          /file\.\|\(\n.*\)\{3\}/!b1
         }
     /\<is\s*an\s*example\s*file\./p
     D' file

ที่เก็บไม่เกิน 4 บรรทัด (เพราะ 4 คำในรูปแบบ) ในหน่วยความจำ ( \(\n.*\)\{3\})


5
ในขณะที่ฉันแน่ใจว่าคุณรู้ว่า-zตัวเลือกที่grepจะรักษาบรรทัดใหม่เป็นตัวอักษรข้อความธรรมดาและมองหา nul ไบต์เพื่อแยกบันทึก ในไฟล์ข้อความที่ไม่มี nul ไบต์ (เช่นกรณีทั่วไป) grep -zจะถือว่าไฟล์ทั้งหมดเป็นหนึ่งบรรทัด ดังนั้น (1) สิ่งนี้ทำให้เกิดคำถามว่ามันสามารถจัดการกับไฟล์ขนาดใหญ่ได้ดีแค่ไหนและ (2) หากพบการแข่งขันมันจะเขียนไฟล์ทั้งหมดโดยไม่ให้เบาะแสเกี่ยวกับตำแหน่งของการแข่งขัน นอกจากนี้ (3) OP กล่าวว่า“ความนึกคิดรักษาลำดับของพื้นที่สีขาวเป็นพื้นที่เดียวใด ๆ” ดังนั้นคุณควรใช้และเพิ่ม\s+ -E
G-Man กล่าวว่า 'Reinstate Monica'

1
@ G-Man ขอบคุณสำหรับความคิดเห็น โปรดดูคำตอบที่แก้ไข
Costas

1
(0) อา-o; ฉันลืมไปตลอดเลย วิธีการใช้งานที่ชาญฉลาด (1) grepคำตอบใหม่ของคุณเริ่มต้นขึ้น^[\n]*; [^\n]*ที่พิมพ์ผิดเป็น (2) ฉันพูด\s+อย่างจงใจ  be\s*littleจะตรงbelittleและจะตรงกับcare\s*less carelessแต่ฉันคิดว่านั่นเป็นปัญหาเล็กน้อย และถ้าคุณไม่ต้องการที่จะใช้-Eคุณสามารถใช้“รุ่นของชายยากจนคน” ของคือ\s+ \s\s*(3) sedคำสั่งที่ดี มันอาจล้มเหลวหากมีบรรทัดว่าง (ดังนั้นวลีสี่คำสามารถแพร่กระจายมากกว่าสี่บรรทัด); s/\n\s*\n/\n/ผมสามารถที่จะแก้ไขปัญหาที่โดยการเพิ่ม
G-Man กล่าวว่า 'Reinstate Monica'

@ G-Man ขอบคุณมาก ความคิดเห็นของคุณมีประโยชน์มาก ฉันพยายามโพสต์รหัสพกพามากขึ้นหรือน้อยลงเพราะสมาชิกที่มีชื่อเสียงผลักดันให้ฉันทำเช่นนั้นทุกครั้ง อย่างไรก็ตามโดยที่-Eคุณไม่สามารถใช้เหล็ก+ใน\s\+แบบฟอร์มได้ เส้นที่ว่างด้านในของลวดลายดูเหมือนว่าจะถูกออกแบบมา
Costas

ฉันคิดว่าเอกสารเลขหน้าเหมือนRFCs - ISTR ที่หน้าคนดูเหมือนในบางระบบ (หรือไม่ ) - แต่ในความคิดต่อไปมันเกิดขึ้นกับฉันว่าเอกสารดังกล่าวส่วนใหญ่มีส่วนหัวของหน้าและ / หรือท้ายกระดาษ (s) ที่จะต้องถูกถอดออกก่อนที่คุณจะหวังกับgrepพวกเขาสำหรับวลี
G-Man กล่าวว่า 'Reinstate Monica'

7

ลองสิ่งนี้:

pcregrep -M '\bThis\s+is\b' <<EOT
This
is
an example
file.
EOT

ฉันต้องพิมพ์\s5 ครั้งหรือไม่หากฉันค้นหา "นี่เป็นรูปแบบที่ยาวมาก"
Nikana Reklawyks

1
ใช่: จุด\sตรงกับช่องว่างและขึ้นบรรทัดใหม่คือ "ช่องว่าง"
lcd047

ฉันหมายถึงจะเกิดอะไรขึ้นถ้าไฟล์นั้นอยู่This\nis a very\nlong patternและฉันไม่รู้ว่าตัวแบ่งบรรทัดเกิดขึ้นที่ใด ฉันต้องค้นหาThis\sis\sa\svery\slong\spatternใช่ไหม (ซึ่งน่าเบื่อเมื่อความยาวของลวดลายเพิ่มขึ้นหรือถูกวางจากที่อื่น)
Nikana Reklawyks

2
pcregrep -M "$( echo 'This is a very long pattern' | sed 's/ /\\s+/g' )" fileแล้วคุณจะทำเช่นนี้
lcd047
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.