ฉันจะแก้ไขบรรทัดที่แตกในตำแหน่งที่ไม่ถูกต้องได้อย่างไร


11

ไฟล์ข้อความของฉันมีลักษณะเช่นนี้:

This is one
sentence that is broken.
However this is a good one.
And this
one is
somehow, broken into
many.

ฉันต้องการลบอักขระบรรทัดใหม่ต่อท้ายสำหรับบรรทัดใด ๆ ที่ตามด้วยบรรทัดที่ขึ้นต้นด้วยตัวอักษรตัวพิมพ์เล็ก

ดังนั้นควรเป็น:

This is one sentence that is broken.
However this is a good one.
And this one is somehow, broken into many.

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

แก้ไข: มีคำตอบที่ดีจริงๆที่นี่ แต่ฉันเลือกที่จะยอมรับคำตอบแรกที่ทำงานและเร็วที่สุด ขอบคุณทุกคนมาก!


1
น้ำยาง? ปัญหาคือคุณไม่ได้ระบุกฎสำหรับการแบ่งประโยคที่เหมาะสม คุณต้องการใส่ทุกอย่างให้พร้อมและรวมถึงเครื่องหมายวรรคตอนสุดท้ายของประโยคในบรรทัดเดียวหรือไม่? แต่ถ้าคุณมีประโยคยาว ๆ มันจะวิ่งออกไปจากขอบหน้าต่างแสดงผลของคุณ?
jamesqf

1
ฉันสงสัยว่าคุณกำลังพยายามแก้ไขอะไรจริงๆ บางทีคุณควรใช้การจัดรูปแบบมาร์คดาวน์?
Wildcard

@JeffSchaller ขอบคุณสำหรับการเตือน! ฉันพลาดอย่างใด :)

คำตอบ:


7

ลอง

awk '$NF !~ /\.$/ { printf "%s ",$0 ; next ; } {print;}' file

ที่ไหน

  • $NF !~ /\.$/ จับคู่บรรทัดที่องค์ประกอบสุดท้ายไม่ได้ลงท้ายด้วยจุด
  • { printf "%s ",$0 พิมพ์บรรทัดนี้ด้วยพื้นที่การติดตามและไม่ป้อนบรรทัด
  • next ; } เรียกบรรทัดถัดไป
  • {print;} และพิมพ์

ฉันแน่ใจว่าจะมีsedตัวเลือก

หมายเหตุ: สิ่งนี้จะทำงานกับการลงท้ายบรรทัดด้วยจุดอย่างไรก็ตามเงื่อนไขในประโยคที่ขึ้นต้นด้วยตัวอักษรตัวพิมพ์ใหญ่จะไม่ถูกรวมเข้าด้วยกัน ดูคำตอบของStéphane Chazelas


หากคุณชอบคนที่ฉลาด (หลายคนไม่ชอบ)awk 'ORS=$NF~/\.$/?"\n":" "'
dave_thompson_085

10

ด้วยawk:

awk -v ORS= '{print (NR == 1 ? "" : /^[[:lower:]]/ ? " " : RS) $0}
             END {if (NR) print RS}'

นั่นคืออย่าผนวกตัวคั่นเร็กคอร์ดในแต่ละบรรทัด (ORS ว่าง) แต่ย่อหน้าตัวคั่นบันทึกก่อนบรรทัดปัจจุบันถ้าไม่ได้อยู่ในบรรทัดแรกและบรรทัดปัจจุบันไม่ได้เริ่มต้นด้วยตัวอักษรตัวพิมพ์เล็ก มิฉะนั้นเติมอักขระเว้นวรรคแทนยกเว้นในบรรทัดแรก


เมื่อฉันเรียกใช้คำบางคำจะถูกต่อกัน ยกตัวอย่างเช่นAnd thisone issomehow, broken intomany.ผมไม่ทราบawkแต่เส้นควรจะร่วมกับ<space>นอกเหนือไปRS? หรือเป็นข้อผิดพลาดของผู้ใช้นี้?
B Layer

@ ผู้เล่นเห็นดีขอบคุณ ควรได้รับการแก้ไขแล้ว
Stéphane Chazelas

ไม่มีปัญหา. แม้ว่าจะมีสิ่งหนึ่งที่สงสัยว่ามีผู้โหวต 11 คนมาจากไหน จะต้องดีถ้ามีคนคิดว่าคุณพูดถูกเสมอ ;)
B Layer

4

ใน Perl:

#!/usr/bin/perl -w
use strict;
my $input = join("", <>);
$input =~ s/\n([a-z])/ $1/g;
print $input;

ในทางเทคนิคคุณต้องการแทนที่ "การขึ้นบรรทัดใหม่ตามด้วยตัวอักษรพิมพ์เล็ก" ด้วย "ช่องว่างและตัวอักษรพิมพ์เล็ก" ซึ่งเป็นสิ่งสำคัญของสคริปต์ Perl ด้านบน:

  1. inputอ่านในการป้อนข้อมูลสตริง
  2. อัปเดตinputตัวแปรให้เป็นผลลัพธ์ของการค้นหาและแทนที่
  3. พิมพ์ค่าใหม่

1
สิ่งที่ดี!! แปลเป็นหนึ่งซับperl -0777 -pe 's/\n([a-z])/ $1/g'และสามารถทำในทำนองเดียวกันกับ GNU sed เป็นsed -zE 's/\n([a-z])/ \1/g'(สมมติว่าอินพุตไม่มีอักขระเป็นโมฆะ)
Sundeep

3
@Sundeep หรือperl -Mopen=locale -0777 -pe 's/\n(?=[[:lower:]])/ /g'เพื่อไม่ให้ จำกัด ตัวอักษร ASCII
Stéphane Chazelas

4

ด้วยsedคุณสามารถใช้N;P;Dวงรอบ (เพื่อให้มีสองบรรทัดเสมอในพื้นที่รูปแบบและถ้าอักขระตัวแรกหลังจากขึ้นบรรทัดใหม่เป็นตัวพิมพ์เล็กให้เปลี่ยนเป็นบรรทัดใหม่ด้วยช่องว่าง) และtest - วิธีนั้นหลังจากแต่ละsubstitution คุณรีสตาร์ทวงจร:

sed -e :t -e '$!N;/\n[[:lower:]]/s/\n/ /;tt' -e 'P;D' infile

1
ฉันคิดว่าฉันเห็นสิ่งที่เกิดขึ้นที่นี่ แต่คำตอบที่ขยายจะช่วยพวกเราที่ไม่ได้ใช้ลูปเซดและช่องว่างรูปแบบบ่อยมาก
Joe

@ Joe - สิ่งที่คุณหมายถึง"ไม่ได้ใช้พื้นที่รูปแบบมากมักจะ" ? นั่นคือสิ่งที่ดำเนินการเกือบทั้งหมด - พื้นที่ถือเป็น "พื้นที่เก็บข้อมูล" - คุณไม่สามารถทำอะไรกับข้อมูลในขณะที่มันมี อย่างไรก็ตามฉันได้อธิบายรายละเอียดเกี่ยวกับวิธีการN;P;Dทำงานของรอบที่นี่ดังนั้นฉันจะไม่ข้ามมันอีก ความแตกต่างที่นี่คือการtตรวจสอบว่ามีบางสิ่งถูกแทนที่หรือไม่ - หากการทดสอบประสบความสำเร็จเราจะแยกไปที่ด้านบนสุดของสคริปต์ไม่เช่นนั้นจะไม่มีอะไรมาแทนที่และP;Dดำเนินการ แจ้งให้เราทราบหากยังไม่ชัดเจน
don_crissti

3

การใช้sedและfmt:

$ sed -e '1n; s/^[[:upper:]]/\n&/' input.txt | fmt
This is one sentence that is broken.

However this is a good one.

And this one is somehow, broken into many.

สคริปต์ sed แทรกบรรทัดใหม่ก่อนทุกบรรทัดที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่ (ยกเว้นบรรทัดแรกของอินพุต) sedเอาต์พุตของจะถูกส่งไปfmtยังเพื่อจัดรูปแบบย่อหน้าผลลัพธ์ใหม่

หรือใช้parหากคุณติดตั้งไว้ เป็นอีกหนึ่งการปฏิรูปย่อหน้า แต่มีความสามารถมากกว่าfmtด้วยฟีเจอร์และตัวเลือกมากมาย

โปรดทราบว่าจะมีบรรทัดว่างระหว่างแต่ละย่อหน้า ย่อหน้าควรแยกออกจากกันด้วยบรรทัดว่างอย่างน้อยหนึ่งบรรทัด หากไม่มีบรรทัดว่างตัวอย่างการป้อนข้อมูลทั้งหมดของคุณจะถูกจัดรูปแบบเป็นย่อหน้าหลายประโยคเช่น:

$ fmt input.txt
This is one sentence that is broken.  However this is a good one.
And this one is somehow, broken into many.

หากคุณต้องการลบบรรทัดว่างหลังจากทำการฟอร์แมตใหม่sedอีกครั้ง แต่จะลบบรรทัดว่างทั้งหมดรวมถึงรายการที่อาจอยู่ในอินพุตต้นฉบับ เช่น

$ sed -e '1n; s/^[[:upper:]]/\n&/' input.txt | fmt | sed -e '/^$/d'
This is one sentence that is broken.
However this is a good one.
And this one is somehow, broken into many.

3

อีกวิธีที่คุณสามารถทำได้คือ:

perl -lpe '$\ = /\.$/ ? $/ : $"' data

ขัดแย้ง: $\=> ORS, $/=> IRS= \n, $"=space

perl -pe '$_ .= <>, eof or redo if s/[^.]\K\n/ /' data

sed -e '
   :a
      /\.$/!N
      s/\n/ /
   ta
' data

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