วิธีการตรวจสอบจุดสิ้นสุดของบรรทัดด้วย sed


15

sedฉันกำลังมองหาวิธีการที่จะดำเนินการเพียงการเปลี่ยนเมื่อตัวละครสุดท้ายคือขึ้นบรรทัดใหม่โดยใช้

ตัวอย่างเช่น

lettersAtEndOfLine

ถูกแทนที่ แต่นี่ไม่ใช่:

lettersWithCharacterAfter&

เนื่องจากsedทำงานไม่ดีกับการขึ้นบรรทัดใหม่จึงไม่ง่ายเหมือน

$ sed -E "s/[a-zA-Z]*\n/replace/" file.txt

สิ่งนี้จะสำเร็จได้อย่างไร

คำตอบ:


21

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

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

หากคุณต้องการแทนที่สิ่งที่ตรงกับรูปแบบ[A-Za-z]*ที่จุดสิ้นสุดของบรรทัดด้วยบางสิ่งบางอย่างแล้วยึดรูปแบบเช่นนี้:

[A-Za-z]*$

... จะบังคับให้จับคู่ที่ส่วนท้ายของบรรทัดและไม่มีที่อื่น

อย่างไรก็ตามเนื่องจากไม่[A-Za-z]*$ตรงกับสิ่งใด (ตัวอย่างเช่นสตริงว่างอยู่ที่ท้ายบรรทัดทุกบรรทัด) คุณต้องบังคับการจับคู่ของบางอย่างเช่นโดยระบุ

[A-Za-z][A-Za-z]*$

หรือ

[A-Za-z]\{1,\}$

ดังนั้นบรรทัดคำสั่งsedของคุณจะเป็นเช่นนั้น

$ sed 's/[A-Za-z]\{1,\}$/replace/' file.txt

ฉันไม่ได้ใช้-Eสวิตช์ที่นี่เพราะมันไม่จำเป็น ด้วยคุณสามารถเขียน

$ sed -E 's/[A-Za-z]+$/replace/' file.txt

มันเป็นเรื่องของรสนิยม


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Kusalananda

3
sed "s/[a-zA-Z]*$/replace/" input.txt > result.txt

หรือทางยาวที่ไม่จำเป็นซับซ้อน:

ฉันพบว่าสิ่งนี้สามารถทำได้ยังคงใช้ sed ด้วยความช่วยเหลือของ tr คุณสามารถกำหนดอักขระอื่นเพื่อแสดงถึงจุดสิ้นสุดของบรรทัด ต้องใช้อักขระชั่วคราวอื่นในกรณีนี้ "" " ลองใช้ "~" เพื่อเป็นตัวแทนจุดสิ้นสุดของบรรทัด:

tr '\n' '`' <input.txt >output.txt
sed -i "s/`/~`/" output.txt
tr '`' '\n' <output.txt >result.txt

จากนั้นเพื่อทำการค้นหาและแทนที่จริงให้ใช้ "~" แทน "\ n":

sed -i -E "s/[a-zA-Z]*~/replace/" result.txt

จากนั้นทำความสะอาดอักขระพิเศษในบรรทัดอื่น ๆ :

sed -i "s/~//" result.txt

เห็นได้ชัดว่าสิ่งนี้สามารถถูกรวมเข้าด้วยกันทำให้มีลักษณะดังนี้:

tr '\n' '`' <input.txt | sed -e "s/`/~`/" | tr '`' '\n' | sed -E -e "s/[a-zA-Z]*~/replace/" | sed "s/~//" > result.txt

3
ไม่แน่ใจว่าฉันเข้าใจ ... ทำไมคุณไม่ลองยึดท้ายด้วย$? เช่นs/[a-zA-Z]*$/replace/
don_crissti

1
2 คะแนน: 1) คุณควรใช้ดีกว่า\+แทนที่จะใช้ตัวอักษรต่อท้าย*ให้มีตัวอักษรไม่เกิน0ตัว 2) [[:alpha:]]คุณสามารถใช้ตัวอักษรชั้นเรียน ดังนั้น:sed 's/[[:alpha:]]\+$/replace/' file
glenn jackman

@glennjackman แบ็กสแลชสำหรับหน้าเครื่องหมายบวกคืออะไร นั่นจะไม่ตรงกับตัวละครนอกเหนือจากนี้?
Matthew D. Scholefield

1
GNU ไม่-rใช้ตัวเลือกใช้ไวยากรณ์นิพจน์ทั่วไปนี้
เกล็นแจ็คแมน

0

จากตัวอย่างโค้ด (ที่ใช้งานไม่ได้) ที่คุณโพสต์ดูเหมือนว่าคุณต้องการแทนที่บรรทัดใหม่ด้วย ในกรณีนี้การยึดเรกซ์ด้วยตัวเองไม่สามารถช่วยคุณได้ ต่อไปนี้เป็นวิธีแก้ปัญหา:

sed '/[[:alpha:]]\+$/{N;s/[[:alpha:]]\+\n/replace/}' your_file

ทำลายลง:

  • /[a-zA-Z]\+$/{} หมายถึงใช้สิ่งใดก็ตามที่อยู่ภายใน curlies กับบรรทัดที่ตรงกับ regex
  • regex เป็นหนึ่งที่ใช้ทอดสมอเท่าที่เห็นในคำตอบของคุณเอง , การแก้ไขเพื่อนำความคิดเห็นของเกล็นแจ๊กแมนเข้าบัญชี
  • ภายใน curlies Nหมายถึง "ผนวกบรรทัดถัดไปเข้ากับบัฟเฟอร์ที่ใช้งาน" (สิ่งที่sedเรียกว่า 'pattern space')
  • ในที่สุดs///คำสั่งคือการทดแทนที่คุณต้องการ ตอนนี้ใช้งานได้เนื่องจากพื้นที่รูปแบบมีสองบรรทัดต่อเนื่องและขึ้นบรรทัดใหม่จึงเป็นส่วนหนึ่งของมัน

0

เพื่อหาจุดสิ้นสุดของบรรทัดเพียงแค่ใช้$ -sign :

ไม่มีจุดสิ้นสุดของจุดยึดบรรทัด:

sed -n '/pattern/p' file 

ไม่มีจุดสิ้นสุดของจุดยึดบรรทัด:

sed -n '/pattern$/p' file
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.