ลบอักขระบรรทัดใหม่เฉพาะทุกบรรทัด N


16

กำลังประมวลผลข้อความฉันต้องลบอักขระบรรทัดใหม่ทุกสองบรรทัด

ข้อความตัวอย่าง:

this is line one
and this is line two
the third and the
fourth must be pasted too

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

this is line one and this is line two
the third and the fourth must be pasted too

ฉันพยายามwhileลูป แต่ในขณะที่ลูปคือการปฏิบัติที่ไม่ดี เป็นไปได้ที่จะใช้trหรือคำสั่งอื่น ๆ ?


4
ชื่อกล่าวว่า "ทุกบรรทัด N" แต่ในคำถามและตัวอย่างเป็น "ทุก 2 บรรทัด" คำตอบส่วนใหญ่ใช้ได้กับ N = 2 เท่านั้น คุณกำลังมองหาบางอย่างที่เหมาะกับ N ทั้งหมดหรือไม่?
JigglyNaga

นั่นคือกุญแจสำคัญ ทุกคนตอบคำถาม 2 บรรทัด แต่ฉันจะต้องใช้ N = 3 หรือ N = 4
jomaweb

คำตอบ:


24

paste(เช่นยูทิลิตี้ง่ายๆ POSIX มาตรฐานเช่นtr) เป็นเครื่องมือของคุณ

สมมติว่าคุณต้องการให้อักขระบรรทัดใหม่เหล่านั้นถูกแทนที่ด้วยเว้นวรรคแทนที่จะลบออกดังตัวอย่าง:

paste -d ' ' - - < file

หรือ:

paste -sd ' \n' file

แทนที่' 'ด้วย'\0'หากคุณต้องการลบออกจริงๆ

หากต้องการแทนที่ 2 จาก 3:

paste -sd '  \n' file

1 จาก 3 เริ่มต้นด้วยวินาที:

paste -sd '\n \n' file

และอื่น ๆ

อีกสิ่งที่ดีด้วยpasteคือมันจะไม่ออกจากสายไม่สิ้นสุด ตัวอย่างเช่นหากคุณลบทุกบรรทัดใหม่ในไฟล์ (เช่นเดียวกับtr -d '\n' < fileหรือtr '\n' ' ' < file) คุณจะไม่มีบรรทัดเลยเพราะบรรทัดจะต้องถูกยกเลิกด้วยอักขระขึ้นบรรทัดใหม่ ดังนั้นโดยทั่วไปจะใช้ดีกว่าpasteแทน (เช่นในpaste -sd '\0' fileหรือpaste -sd ' ' file) ซึ่งจะเพิ่มอักขระบรรทัดใหม่ต่อท้ายที่จำเป็นเพื่อให้มีข้อความที่ถูกต้อง


11

ด้วยGNU ที่ทันสมัย

sed -rz 's/\n([^\n]*\n)/ \1/g' sample.text

และawk

awk '{getline line2;print $0, line2}' sample.text

3
sedวิธีการดังกล่าวหมายถึง slurping ไฟล์ทั้งหมดในหน่วยความจำ (หากไม่มีไฟล์ NUL) และทำการทดแทน regexp ที่มีราคาแพง ฉันไม่เห็นประโยชน์มากกว่าsed 'N;s/\n/ /'วิธีมาตรฐาน
Stéphane Chazelas

6

ใช้sedสำหรับสิ่งนี้ตามที่แสดงด้านล่าง:

SHW@SHW:/tmp $ cat a
this is line one
and this is line two
the third and the
fourth must be pasted too

SHW@SHW:/tmp $ sed 'N;s/\n/ /' a -i

SHW@SHW:/tmp $ cat a
this is line one and this is line two
the third and the fourth must be pasted too

4

อีกวิธีหนึ่งคือการใช้xargs:

$ < txt xargs -d '\n' -n 2 echo
this is line one and this is line two
the third and the fourth must be pasted too

ที่ไหน

$ cat txt
this is line one
and this is line two
the third and the
fourth must be pasted too

แม้ว่าการแก้ปัญหานี้จะค่อนข้างมากเพราะechoกระบวนการถูกดำเนินการสำหรับแต่ละบรรทัด ... ดังนั้นนอกเหนือจากตัวอย่างของเล่นควรใช้โซลูชันที่อิง awk / sed หรือคล้ายกัน


1
echoคุณจะประสบปัญหากับอักขระเครื่องหมายทับขวาหรือบางบรรทัดที่ขึ้นต้นด้วย-(เช่น--helpหรือ-neneกับ GNU echo) ทั้งนี้ขึ้นอยู่กับการนำไปใช้ของคุณ โปรดทราบด้วยว่านั่น-dคือส่วนขยาย GNU
Stéphane Chazelas

เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับechoคุณสามารถใช้สิ่งนี้:< txt xargs -d '\n' -n 2 printf -- '%s %s\n'
nyuszika7h

4

นี่เป็นเรื่องง่ายมากในกลุ่ม ในการเข้าร่วมทุกบรรทัดให้ใช้Jคำสั่งจากนั้นใช้%normคำสั่งเพื่อใช้กับทุกบรรทัดพร้อมกัน ตัวอย่างเช่น

:%norm J<CR>

(ในกรณีที่คุณไม่คุ้นเคยกับเสียงเรียกเข้า <CR>ก็หมายถึงป้อน)

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

:%norm 9J<CR>

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

vim myfile -c '%norm J' -c 'wq'

ผู้ลงคะแนนเสียงสนใจจะอธิบายสิ่งที่ฉันสามารถทำได้เพื่อปรับปรุงคำตอบนี้หรือไม่?
DJMcMayhem

3
$ awk '{printf "%s%s",$0,(NR%2?" ":"\n")}' sample.txt
this is line one and this is line two
the third and the fourth must be pasted too

พิมพ์ออกมาแต่ละบรรทัด$0ตามด้วยช่องว่างหรือขึ้นบรรทัดใหม่ขึ้นอยู่กับว่าหมายเลขบรรทัดNRเป็นเลขคี่หรือคู่

การแสดงออกNR%2?" ":"\n"เป็นคำที่สาม การแสดงออกNR%2ประเมินค่าเป็นจริง (ไม่ใช่ศูนย์) หากหมายเลขแถวเป็นเลขคี่ ในกรณีนิพจน์ประกอบไปด้วยจะคืนค่าช่องว่าง หากประเมินเป็นเท็จ (ศูนย์) แล้วขึ้นบรรทัดใหม่จะถูกส่งกลับ

ทางเลือก

ตามที่ Costas แนะนำไว้ในความคิดเห็น:

$ awk '{ORS=(NR%2?" ":RS)}1' sample.txt
this is line one and this is line two
the third and the fourth must be pasted too

ที่นี่คำสั่งที่ประกอบไปด้วยNR%2?" ":RSจะใช้ในการส่งกลับช่องว่างหรือตัวคั่นบันทึกการป้อนข้อมูล ( RSเริ่มต้น = ขึ้นบรรทัดใหม่) ORSค่านี้จะได้รับมอบหมายให้แยกบันทึกเอาท์พุท 1ในตอนท้ายของคำสั่งที่เป็น awk ของชวเลขลับสำหรับการพิมพ์การบันทึก


คุณยังสามารถบันทึกได้ 3 ตัวอักษร: ()วงเล็บและช่องว่างหลังprintf;)
maxschlepzig

1
ประกอบไปด้วย? Oh! 'NR%2{printf("%s ",$0);next}1'
Costas

ด้วยคำตอบของ maxschlepzigและงบประกอบไปด้วย:'{ORS=(NR%2?" ":RS)}1'
Costas

@ Costas ฉันชอบสิ่งนั้น คำตอบอัพเดทด้วยORSวิธีแก้ปัญหา
John1024

2

โซลูชันทั่วไปแทนที่5ด้วยจำนวนบรรทัดที่ต้องการ

$ # eof to ensure last line has newline ending
$ seq 16 | perl -pe 's/\n/ / if ++$i%5 && !eof'
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16

$ # or just use pr
$ seq 16 | pr -5ats' '
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16

1

คุณสามารถใช้awkสิ่งนี้:

$ awk '{c="\n"} NR%2 {c=" "} { printf("%s%s", $0, c) } ' txt

มันผลิต:

this is line one and this is line two
the third and the fourth must be pasted too

ที่อยู่:

$ cat txt
this is line one
and this is line two
the third and the
fourth must be pasted too

การawkดำเนินการจะดำเนินการสำหรับแต่ละบรรทัดตัวแปรพิเศษที่$0อ้างอิงถึงบรรทัดปัจจุบันNRคือหมายเลขบรรทัดปัจจุบัน (เริ่มต้นที่ 1) การดำเนินการที่สองได้รับการปกป้องโดยการแสดงออกNR%2ซึ่งเป็นการดำเนินการแบบโมดูโล ดังนั้นc=" "จะถูกดำเนินการหากNR%2เป็นจริงคือสำหรับหมายเลขบรรทัดคี่

awkไวยากรณ์คือ C เหมือน แต่องค์ประกอบบางอย่างเป็นตัวเลือกในบางบริบท - เช่นอัฒภาค


cตัวแปรของคุณคือORS:'NR%2{ORS=" "}1;{ORS=RS}'
Costas

0

การใช้ed:

$ cat text
this is line one
and this is line two
the third and the
fourth must be pasted too
this is line one
and this is line two
the third and the
fourth must be pasted too

$ ed text <<'END_ED'
g/./s/$/ /\
j
w text.new
END_ED
164
164

$ cat text.new
this is line one and this is line two
the third and the fourth must be pasted too
this is line one and this is line two
the third and the fourth must be pasted too

edแก้ไขคำสั่งจะแต่ละบรรทัด (gใช้ชุดของการแก้ไขคำสั่งไปยังทุกบรรทัดตรงกับการแสดงออกปกติที่กำหนด), เพิ่มอักขระช่องว่างที่สิ้นสุดและเข้าร่วมกับบรรทัดถัดไป text.newจากนั้นก็จะเขียนข้อความส่งผลไปยังแฟ้มที่เรียกว่า


0

ด้วยทับทิม

ฉันคิดว่าแต่ละบล็อกของnเส้นจะเข้าร่วม สมมติว่าn = 3ไฟล์อินพุตคือ'infile''outfile'และผลที่จะได้รับการเขียนไปยังแฟ้ม

สร้างไฟล์

Ruby -e "File.write 'infile', <<_
> Line 1
> Line 2
> Line 3
> Line 4
> Line 5
> Line 6
> Line 7
> _"

ยืนยันเนื้อหาของไฟล์

ruby -e "p File.read 'infile'"
  # "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\n"

ลบบรรทัดใหม่และเขียนไปที่ไฟล์

ruby -e "File.write 'outfile', File.readlines('infile').
  each_with_index { |line,i| line.chomp! unless (i+1)%3==0 }"

ยืนยันเนื้อหา

ruby -e "puts File.read 'outfile'"
  # ["Line 1", "Line 2", "Line 3\n", "Line 4", "Line 5", "Line 6\n", "Line 7"]

1
สิ่งที่ดี. ในทางทฤษฎีrubyเป็นหัวข้อนอก U & L แต่เนื่องจากคุณใช้มันจากบรรทัดคำสั่งด้วยruby -eนั่นทำให้มันเพียงพอในหัวข้อ
grochmal
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.