สามารถลบอักขระขึ้นบรรทัดใหม่ 'สองเท่า' ได้หรือไม่


25

ฉันมีเอกสารที่มีบรรทัดว่างเปล่าจำนวนมาก

ฉันจะลบออกได้อย่างไรเมื่อมี 2 หรือมากกว่ารวมกัน

ฉันลองsed "s/\n\n//"ไฟล์แล้วแต่ใช้งานไม่ได้ ไม่มีข้อผิดพลาด


3
ฉันจะอ่านคุณอย่างถูกต้องหรือไม่ถ้าคุณไม่ต้องการลบบรรทัดว่างเปล่าทั้งหมด แต่ถ้ามันเป็นสองคนหรือมากกว่านั้น ดังนั้นไม่เดียวบรรทัดว่าง?
Runium

1
และถ้ามันเป็นสองเส้นหรือมากกว่านั้นจะต้องลบทั้งหมดหรือเพียงแค่เส้นเดียว?
Hauke ​​Laging

คำตอบ:


42

เพียงเพื่อลบบรรทัดว่าง:

sed  '/^$/d'

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


แน่นอน! +1 เพื่อความหรูหราที่เรียบง่าย
terdon

2
sedสามารถจัดการหลายบรรทัดผ่านคุณสมบัติ "pattern space" / "hold space" แต่ฉันรู้สึกว่ามันซับซ้อนเกินไป ;-)
Hauke ​​Laging

สิ่งนี้จะไม่ทำงานตามที่ต้องการถ้าตัวอักษรตัวแรกของไฟล์ขึ้นบรรทัดใหม่
Chris Down

1
ที่จะทำให้มันทำงานเมื่อตัวอักษรตัวแรกคือการขึ้นบรรทัดใหม่ (ถ้าที่จริงต้องการ) แล้วคุณสามารถใส่คำสั่งที่มีอยู่ในเชิงลบ1!(ตรงกับทุกคนยกเว้นบรรทัดที่ 1) sed '1!{/^$/d'}ดังนี้:
Toby Speight

1
@AaronFranke - ใช่ แต่นั่นเป็นแง่มุมของวิธีที่เชลล์ Linux จัดการการเปลี่ยนเส้นทาง '>' เชลล์มองไปที่บรรทัดคำสั่งเห็นการเปลี่ยนเส้นทาง '>' ของ stdout ไปยังไฟล์สร้างไฟล์นั้นและจากนั้นเรียกใช้sedเท่านั้น การสร้างไฟล์เป็นหลักจะลบไฟล์ที่มีอยู่ด้วยชื่อเดียวกัน sed '/^&/d' file.txt > otherfile.txtจะทำงาน.
Bruce Ediger

24

sedไม่จำเป็นต้อง grepจะทำ:

grep .

(นั่นคือgrepSPC จุดที่ตรงกับบรรทัดใด ๆ ที่มีอักขระอย่างน้อยหนึ่งตัว)

นอกจากนี้ยังมี:

tr -s '\n'

(บีบลำดับอักขระขึ้นบรรทัดใหม่ใด ๆ เป็นหนึ่ง)

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


2
สิ่งนี้จะไม่ทำงานตามที่ต้องการถ้าตัวอักษรตัวแรกของไฟล์ขึ้นบรรทัดใหม่: sprunge.us/FLAJ
Chris Down

7

sedไม่ใช่เครื่องมือที่ดีที่สุดสำหรับสิ่งนั้นเนื่องจากเป็นบรรทัดตามและถือว่า\nเป็นอักขระที่สิ้นสุดของบรรทัดซึ่งมีความซับซ้อนการได้เห็น @Bruce Ediger คำตอบ sedอาจเป็นเครื่องมือที่สมบูรณ์แบบสำหรับงาน แต่ก็มีตัวเลือกอื่น ๆ :

  1. Perl

    perl -ne 'print if /./' file.txt
    

    หรือ

    perl -pe '$/=""; s/\n+/\n/;' file.txt 
    

    ขอบคุณ@ruakhที่ทำให้ฉันไปและอ่านสิ่งนี้ :

    $ /

    ตัวคั่นเรคคอร์ดอินพุตบรรทัดใหม่เป็นค่าเริ่มต้น สิ่งนี้มีอิทธิพลต่อความคิดของ Perl ว่า "บรรทัด" คืออะไร ทำงานเหมือนตัวแปร RS ของ awk รวมถึงการปฏิบัติกับบรรทัดว่างเป็นเทอร์มิเนเตอร์หากตั้งค่าเป็นสตริงว่าง (บรรทัดว่างไม่สามารถมีช่องว่างหรือแท็บใด ๆ ) คุณสามารถตั้งให้มันเป็นสตริงที่มีหลายตัวละครเพื่อให้ตรงกับจุดสิ้นสุดของตัวละครหลายตัวหรือเพื่อยกเลิกการอ่านจนจบไฟล์ การตั้งค่าเป็น "\ n \ n" หมายถึงบางสิ่งที่แตกต่างจากการตั้งค่าเป็น "" เล็กน้อยหากไฟล์มีบรรทัดว่างที่ต่อเนื่องกัน การตั้งค่าเป็น "" จะถือว่าบรรทัดว่างสองบรรทัดหรือมากกว่านั้นต่อเนื่องกันเป็นบรรทัดว่างเดี่ยว การตั้งค่าเป็น "\ n \ n" จะถือว่าสุ่มตัวอย่างว่าอักขระอินพุตถัดไปเป็นของย่อหน้าถัดไปแม้ว่าจะเป็นบรรทัดใหม่

  2. เพ่งพิศ / awk

    awk '$1' file.txt
    

    ว่าการทำงานจะยกตัวอย่างเช่นที่โพสต์ แต่เป็น@Stephane Chazelasชี้ให้เห็นว่ามันจะยังสายการลบซึ่งครั้งแรกที่ช่อง 0"ดูเหมือน" สิ่งนี้แข็งแกร่งกว่า:

    awk NF file.txt
    

สำหรับ Perl perl -pe 's/\n+/\n/ file.txtจะทำอย่างไรตัวคั่นเรคคอร์ดอินพุตไม่เกี่ยวข้องสำหรับการใช้งานนี้
vonbrand

@ vonbrand no perl -peหรือperl -neทำงานทีละบรรทัด \n+จะไม่ตรงกันเนื่องจากมีการใช้งานในบรรทัดเดียวเท่านั้น นั่นเป็นสาเหตุที่คุณต้องตั้งค่า$/หรือใช้-0ไฟล์ slurp ทั้งไฟล์: perl -0pe 's/\n+/\n/' file.
terdon

6

คุณหมายถึงการลบอะไร ลบที่ซ้ำกัน (บรรทัดว่างหลายบรรทัด) หรือลบทั้งหมด?

หากคุณต้องการลบไฟล์ซ้ำนี่คือวิธีการใช้ sed:

sed '$!N; /^\(.*\)\n\1$/!P; D'

มันจำลองuniqคำสั่ง

ทางเลือกที่ดีที่สุดคือการใช้awk:

awk NF <filename>

sedส่วนหนึ่งของงานได้ดี! แนะนำให้คนนี้เป็นคำตอบที่ดีที่สุด
Akito

2

สำหรับคำตอบส่วนใหญ่เหล่านี้จำเป็นอย่างยิ่งที่จะต้องลบช่องว่างต่อท้าย การลบบรรทัดใหม่ขึ้นสองเท่าจะเป็นการลบบรรทัดว่างทั้งหมด (คิดเกี่ยวกับสิ่งนี้).

ตีความอย่างแท้จริง OP ต้องการ "ลบบรรทัดว่างทั้งหมดออกจากไฟล์หากมีบรรทัดว่างซ้ำ ๆ "

ผู้ใช้ทั่วไปต้องการ "ลบบรรทัดว่างที่ทำซ้ำเท่านั้น"

ในการทำเช่นนี้ให้ลากส่วนท้ายของไวท์สเปซออกก่อนและไปป์ที่ cat -s

sed  s/[[:space:]]*$// | cat -s

และสิ่งนี้จะไม่ลบบรรทัดว่างที่นำหน้าหรือต่อท้ายเปล่า


ลดลง แต่สิ่งนี้ใช้งานได้จริงหรือ ไม่มีความเห็น ?
mckenzm

1
ฉันโหวตให้คุณ ... คุณรู้ ... ตอบคำถาม =) ฉันไม่อยากเชื่อว่าการตอบสนองของ Bruce Ediger จะเพิ่มสูงขึ้นเมื่อลบทุกบรรทัดว่าง หากมีคนถามถึงวิธีลบบรรทัดว่างที่ซ้ำกันฉันไม่สามารถจินตนาการถึงสถานการณ์ใด ๆ ที่การลบบรรทัดว่างทั้งหมดจะเป็นวิธีแก้ปัญหาที่ยอมรับได้ แต่อะไรก็ตาม มีหน้าเว็บไซต์สำหรับ sed ที่ครอบคลุมสิ่งนี้โดยวิธีการ: gnu.org/software/sed/manual/sed.html#cat-_002ds
Todd Walton

2

หากคุณต้องการเก็บบรรทัดว่างไว้หนึ่งบรรทัดสำหรับลำดับบรรทัดว่างใด ๆ ที่คุณอาจทำ:

sed -e '/./b' -e :n -e 'N;s/\n$//;tn'

1
นี่เป็นคำตอบเดียว (นอกเหนือจากcat -s) ที่ทำตามจริงในสิ่งที่คำถามถามเมื่อฉันเข้าใจ (และมันดีกว่าcat -sเพราะฉันสามารถใช้sed -iกับมันได้)
Matthew

-2

ลองsed -e 's#\\n\\n#\\n#g' input.file > output.fileใช้/ทั้งสองอย่างเป็นตัวคั่นฟิลด์และส่วนหนึ่งของ regex ของคุณอาจเป็นปัญหา


2
เพิ่งให้สิ่งนี้วนกับหนึ่งในไฟล์ของฉันที่มีการขึ้นบรรทัดใหม่สองและสามในลำดับ ไม่ได้ผลเลยสำหรับฉัน
ไวยากรณ์

-3

ใช้คำสั่งนี้:

tr -s '\r' '\n'

ใช่คำตอบของพวกเขาไม่ทำงานสำหรับฉัน
meow

5
AFAIK คำตอบนี้ไม่ถูกต้อง ฉันแนะนำให้คุณลบ
zuazo

โอ้มันเป็นเพราะไฟล์ของฉันมีการขึ้นบรรทัดใหม่จำนวนมากและการขึ้นบรรทัดใหม่ส่งคืนจริง 0x0d0a
meow

2
ที่จริงแล้วคำสั่งลบบรรทัดที่ซ้ำกันด้วย windows end of line echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'การทดสอบด้วย คำสั่งtrจะแปลทั้งหมด\rเป็น\nและจากนั้นจะบีบทั้งหมด\nเป็นหนึ่งเดียว ดังนั้นมันใช้งานได้ไม่แน่ใจว่าจะทำอย่างไรกับความจริงที่ว่าสิ่งนี้ใช้ได้กับ windows ไม่ใช่ UNIX
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.