เพื่อความแม่นยำ
Some text
begin
Some text goes here.
end
Some more text
และฉันต้องการแยกบล็อกทั้งหมดที่เริ่มต้นจาก "เริ่มต้น" จนถึง "สิ้นสุด"
ด้วย awk เราสามารถทำเช่นawk '/begin/,/end/' text
นั้น
จะทำอย่างไรกับ grep?
เพื่อความแม่นยำ
Some text
begin
Some text goes here.
end
Some more text
และฉันต้องการแยกบล็อกทั้งหมดที่เริ่มต้นจาก "เริ่มต้น" จนถึง "สิ้นสุด"
ด้วย awk เราสามารถทำเช่นawk '/begin/,/end/' text
นั้น
จะทำอย่างไรกับ grep?
คำตอบ:
อัปเดตวันที่ 18 พ.ย. 2559 (เนื่องจากการเปลี่ยนแปลงพฤติกรรมของ grep: grep ด้วยพารามิเตอร์ -P ตอนนี้ไม่สนับสนุน^
และ$
จุดยึด [ใน Ubuntu 16.04 กับเคอร์เนล v: 4.4.0-21-generic]) ( แก้ไขไม่ถูกต้อง (ไม่ใช่ - )
$ grep -Pzo "begin(.|\n)*\nend" file
begin
Some text goes here.
end
หมายเหตุ: สำหรับคำสั่งอื่น ๆ ให้แทนที่ตัวยึด '^' & '$' ด้วยตัวยึดบรรทัดใหม่'\n'
______________________________
ด้วยคำสั่ง grep:
grep -Pzo "^begin\$(.|\n)*^end$" file
หากคุณไม่ต้องการรูปแบบ "เริ่มต้น" และ "สิ้นสุด" ให้ใช้ grep ด้วย Lookbehind และ Lookahead support
grep -Pzo "(?<=^begin$\n)(.|\n)*(?=\n^end$)" file
นอกจากนี้คุณสามารถใช้การ\K
แจ้งเตือนแทน Lookbehind ยืนยัน
grep -Pzo "^begin$\n\K(.|\n)*(?=\n^end$)" file
\K
ตัวเลือกละเว้นทุกอย่างก่อนการจับคู่รูปแบบและละเว้นรูปแบบเอง
\n
ใช้สำหรับหลีกเลี่ยงการพิมพ์บรรทัดว่างจากผลลัพธ์
หรือตามที่ @AvinashRaj แนะนำว่ามี grep ง่าย ๆ ง่ายๆดังต่อไปนี้:
grep -Pzo "(?s)^begin$.*?^end$" file
grep -Pzo "^begin\$[\s\S]*?^end$" file
(?s)
บอก grep เพื่อให้จุดจับคู่อักขระขึ้นบรรทัดใหม่
[\s\S]
จับคู่อักขระใด ๆ ที่เป็นช่องว่างหรือช่องว่างที่ไม่ใช่
และผลลัพธ์ของมันโดยไม่รวม "เริ่มต้น" และ "สิ้นสุด" มีดังต่อไปนี้:
grep -Pzo "^begin$\n\K[\s\S]*?(?=\n^end$)" file # or grep -Pzo "(?<=^begin$\n)[\s\S]*?(?=\n^end$)"
grep -Pzo "(?s)(?<=^begin$\n).*?(?=\n^end$)" file
ดูการทดสอบทั้งหมดของคำสั่งทั้งหมดที่นี่ ( ล้าสมัยเนื่องจากการทำงาน grep กับพารามิเตอร์ -P มีการเปลี่ยนแปลง )
^
ชี้จุดเริ่มต้นของบรรทัดและ$
ชี้จุดสิ้นสุดของบรรทัด สิ่งเหล่านี้ถูกเพิ่มลงใน "เริ่มต้น" และ "สิ้นสุด" เพื่อจับคู่พวกเขาหากพวกเขาอยู่คนเดียวในบรรทัด
ในสองคำสั่งฉันหนี$
เพราะมันยังใช้สำหรับ "การทดแทนคำสั่ง" ( $(command)
) ที่ช่วยให้การส่งออกของคำสั่งเพื่อแทนที่ชื่อคำสั่ง
-o, --only-matching
Print only the matched (non-empty) parts of a matching line,
with each such part on a separate output line.
-P, --perl-regexp
Interpret PATTERN as a Perl compatible regular expression (PCRE)
-z, --null-data
Treat the input as a set of lines, each terminated by a zero byte (the ASCII
NUL character) instead of a newline. Like the -Z or --null option, this option
can be used with commands like sort -z to process arbitrary file names.
grep -Pzo "(?<=begin\n)(.|\n)*(?=\nend)" file
ไม่ต้องการพิมพ์\n
ตัวอักษรที่มีอยู่ในบรรทัดเริ่มต้น
grep -Pzo "(?s)begin.*?end" file
grep -Pzo "begin[\s\S]*?end" file
grep: ein nicht geschütztes ^ oder $ wird mit -Pz nicht unterstützt
การแปลข้อผิดพลาดเป็นสิ่งที่ต้องการ:grep: a not protected ^ or $ is not supported with -Pz
grep
น่าจะเปลี่ยนไป
ในกรณีที่grep
ไวยากรณ์ของคุณไม่รองรับ perl ( -P
) คุณสามารถลองเชื่อมโยงบรรทัดจับคู่รูปแบบจากนั้นขยายบรรทัดอีกครั้งดังนี้:
$ tr '\n' , < foo.txt | grep -o "begin.*end" | tr , '\n'
begin
Some text goes here.
end