ฉันจะลบทุกอย่างได้จนกว่าจะมีรูปแบบและทุกอย่างหลังจากรูปแบบอื่นจากบรรทัดได้อย่างไร


17

ในไฟล์ต่อไปนี้:

Lorem ipsum dolor amet amet, consectetuer adipiscing elit เป็นตัวบ่งชี้ที่ดีที่สุดของคุณ Maecenas rhoncus

ฉันต้องการลบทุกอย่างก่อนconsectetuerและทุกอย่างหลังจากelitนั้น

ผลลัพธ์ที่ฉันต้องการ:

consectetuer adipiscing elit.

ฉันจะทำสิ่งนี้ได้อย่างไร


2
sedคำสั่งที่สามารถ มันสามารถเป็นได้perlหรือแม้กระทั่งทุบตีบริสุทธิ์
muru

@manuel หากคำตอบข้อใดข้อหนึ่งเหล่านี้แก้ไขปัญหาของคุณได้โปรดสละเวลาสักครู่และยอมรับโดยคลิกที่เครื่องหมายถูกทางด้านซ้าย ที่จะทำเครื่องหมายคำถามว่าตอบแล้วและเป็นวิธีที่แสดงความขอบคุณในเว็บไซต์ Stack Exchange
terdon

คำตอบ:


27

ฉันจะใช้ sed

sed 's/^.*\(consectetuer.*elit\).*$/\1/' file

ถอดรหัส sed s / find / replace / syntax:

  • s/^.*- ทดแทนเริ่มต้นที่จุดเริ่มต้นของบรรทัด ( ^) ตามด้วยสิ่งใด ( .*) สูงสุด ...
  • \( - เริ่มบล็อกที่มีชื่อ
  • consectetuer.*elit\.- จับคู่คำแรกทุกอย่าง ( .*) จนถึงคำสุดท้าย (ในกรณีนี้รวมถึงจุดต่อท้าย (Escape)) ที่คุณต้องการจับคู่
  • \) - จบบล็อกที่มีชื่อ
  • จับคู่ทุกอย่างอื่น ( .*) ถึงท้ายบรรทัด ( $)
  • / - จบส่วนค้นหาแทน
  • \1- แทนที่ด้วยบล็อกชื่อระหว่าง\(และ\)เหนือ
  • / - จบการแทนที่

1
คำตอบที่ดี แต่คุณไม่ต้องการ^หรือ$เนื่องจาก sed จะพยายามค้นหาคู่ที่ยาวที่สุด นอกจากนี้คุณอาจพลาดจุดหลังจากelitนั้นคุณสามารถแทรกได้\.ถ้าจำเป็น
asoundmove

2
@asoundmove จับจุดสัมผัสบน "elit" ได้ดี - คุณมีดวงตาที่ค่อนข้างคม! ฉันได้อัปเดตคำตอบของฉันเพื่อรวมจุดหลบหนีในรูปแบบแล้ว ของคุณถูกต้องว่า^และ$ไม่จำเป็น - ฉันทิ้งไว้ที่นั่นเพราะผู้ถามตั้งข้อสังเกต (เดิม) ว่าเขาเป็นผู้เริ่มต้นและนี่อาจเป็นประโยชน์ในบริบทอื่น ๆ
MikeV

ฉันมักจะคัดลอกวางวิธีการแก้ปัญหาและแฮ็คพวกเขาเพื่อให้เหมาะกับความต้องการของฉัน แต่ต้องขอบคุณคำตอบนี้ฉันรู้สึกเหมือนจริงตอนนี้ฉันเข้าใจ คำตอบที่ดี
ไทเลอร์

7

หากทุกบรรทัดgrepมีทั้งเริ่มต้นและสิ้นสุดแล้วรูปแบบวิธีที่ง่ายที่สุดที่จะทำนี้ด้วย แทนที่จะลบจุดเริ่มต้นและจุดสิ้นสุดของแต่ละบรรทัดคุณสามารถส่งออกเนื้อหาระหว่างทั้งสองรูปแบบได้ -oตัวเลือกใน GNU grepoutputs เพียงการแข่งขัน:

grep -o 'consectetuer.*elit' file

หมายเหตุ: ตามที่กล่าวไว้จะใช้งานได้ก็ต่อเมื่อทุกบรรทัดในไฟล์สามารถแยกวิเคราะห์ได้ด้วยวิธีนี้ จากนั้นอีกครั้งนั่นคือ 80% ของกรณีใช้งานทั่วไป


1

สองวงสำหรับ AWK:

$ awk '{for(i=1;i<=NF;i++) {if ($i == "consectetuer") beginning=i; if($i== "elit.") ending=i }; for (j=beginning;j<=ending;j++) printf $j" ";printf "\n"   }' file.txt 
consectetuer adipiscing elit.

gsub ของ AWK:

$ awk '{gsub(/^.*consectetuer/,"consectetuer"); gsub(/elit.*$/,"elit.");print}' file.txt
consectetuer adipiscing elit.

1

วิธี Perl นี่เป็นหลักเหมือนกับคำตอบของ MikeVsed :

perl -pe 's/.*(consectetuer.*elit).*./$1/' file

-pหมายถึง "พิมพ์ทุกบรรทัดหลังจากการใช้สคริปต์ที่กำหนดด้วย-e" s/foo/bar/เป็นผู้ดำเนินการแทน; มันจะเข้ามาแทนที่ด้วยfoo barวงเล็บจับรูปแบบและให้เราใช้ในการเปลี่ยน รูปแบบการจับภาพแรกคือ$1ที่สอง$2และอื่น ๆ

ดังนั้นคำสั่งจะจับคู่ทุกอย่างจนถึงconsectetuer( .*consectetuer) จากนั้นทุกอย่างจนถึงelit( .*elit) แล้วทุกอย่างอื่นจนกว่าจะสิ้นสุดบรรทัด ( .*) และจะแทนที่ด้วยรูปแบบการจับภาพ


1

ฉันไม่แน่ใจว่าทำไมคำถามนี้ถูกแก้ไข " จากไฟล์ " ถึง " จากบรรทัด " ในขณะที่ OP ไม่ได้แยกความเป็นไปได้ในหลาย ๆ บรรทัดแม้ว่าตัวอย่างจะดูเหมือนเป็นหนึ่งบรรทัดเท่านั้น ไม่ว่ามันจะมีประโยชน์อะไรที่จะนำเสนอโซลูชั่นหลายบรรทัดที่นี่

ใช้งานได้สำหรับการข้ามบรรทัด:

from1=consectetuer; to2=elit; a="$(cat file)"; a="$(echo "${a#*"$from1"}")"; echo "$from1${a%%"$to2"*}$to2"

ตัวอย่าง:

[xiaobai@xiaobai tmp]$ cat file
1
abc consectetuer lsl

home

def elit dd
2 consectetuer ABC elit
[xiaobai@xiaobai tmp]$ from1=consectetuer; to2=elit; a="$(cat file)"; a="$(echo "${a#*"$from1"}")"; echo "$from1${a%%"$to2"*}$to2"
consectetuer lsl

home

def elit
[xiaobai@xiaobai tmp]$ 

การอ้างอิง: การขยายพารามิเตอร์เชลล์


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