ฉันจะแทนที่บรรทัดใหม่ (\ n) โดยใช้ sed ได้อย่างไร


1371

ฉันจะแทนที่บรรทัดใหม่ (" \n") ด้วยช่องว่าง (" ") โดยใช้sedคำสั่งได้อย่างไร

ฉันพยายามไม่สำเร็จ:

sed 's#\n# #g' file
sed 's#^$# #g' file

ฉันจะแก้ไขได้อย่างไร


27
trเป็นเครื่องมือที่เหมาะสมสำหรับงานหากแทนที่อักขระเดียวสำหรับอักขระเดียวในขณะที่ตัวอย่างด้านบนแสดงแทนที่ newline ด้วยช่องว่าง .. ในตัวอย่างข้างต้น tr สามารถใช้งานได้ แต่จะ จำกัด ในภายหลัง
Angry 84

9
trในเครื่องมือที่เหมาะสมสำหรับงานเนื่องจากผู้ถามต้องการแทนที่แต่ละบรรทัดใหม่ด้วยช่องว่างดังแสดงในตัวอย่างของเขา การขึ้นบรรทัดใหม่นั้นมีความแปลกใหม่sedแต่ทำได้ง่าย trนี่เป็นคำถามทั่วไป การดำเนินการแทนที่ regex ไม่ได้ดำเนินการโดยtrแต่โดยsedซึ่งจะเป็นเครื่องมือที่เหมาะสม ... สำหรับคำถามที่แตกต่าง
Mike S

3
"tr" สามารถลบบรรทัดใหม่ `tr -d '\ n' 'ได้อย่างไรก็ตามคุณอาจต้องการลบผลตอบแทนที่เป็นสากลมากขึ้น` tr -d' \ 012 \ 015 ''
แอนโธนี

2
คำเตือน: "tr" ทำหน้าที่แตกต่างกันไปตามช่วงอักขระระหว่าง Linux และเครื่อง Solaris รุ่นเก่า (EG sol5.8) EG: `tr -d 'az' 'และ` tr -d' [az] '' เพื่อที่ฉันขอแนะนำให้คุณใช้ "sed" ซึ่งไม่มีความแตกต่างนั้น
แอนโธนี

2
@ MikeS ขอบคุณสำหรับคำตอบ ทำตามที่มีtr '\012' ' ' echoมิฉะนั้นบรรทัดสุดท้ายในไฟล์จะถูกลบด้วย tr '\012' ' ' < filename; echoไม่หลอกลวง
Bernie Reiter

คำตอบ:


1513

ใช้โซลูชันนี้กับ GNU sed:

sed ':a;N;$!ba;s/\n/ /g' file

การดำเนินการนี้จะอ่านไฟล์ทั้งหมดในลูปแล้วแทนที่บรรทัดใหม่ด้วยช่องว่าง

คำอธิบาย:

  1. :aสร้างป้ายผ่านทาง
  2. Nผนวกในปัจจุบันและในบรรทัดถัดไปพื้นที่รูปแบบผ่าน
  3. หากเราอยู่ก่อนบรรทัดสุดท้ายให้แยกสาขาไปยังป้ายกำกับที่สร้างขึ้น$!ba( $!หมายถึงไม่ควรทำในบรรทัดสุดท้ายเนื่องจากควรมีหนึ่งบรรทัดใหม่สุดท้าย)
  4. ในที่สุดการทดแทนจะแทนที่ทุกบรรทัดใหม่ด้วยช่องว่างบนพื้นที่รูปแบบ (ซึ่งเป็นไฟล์ทั้งหมด)

นี่คือไวยากรณ์ที่เข้ากันได้ข้ามแพลตฟอร์มซึ่งทำงานร่วมกับ BSD และ OS X sed(ตามความคิดเห็น @Benjie ):

sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file

อย่างที่คุณเห็นการใช้sedปัญหาอย่างง่ายนี้เป็นปัญหา สำหรับวิธีแก้ปัญหาที่ง่ายและเพียงพอดูคำตอบนี้


45
@Arjan และ Masi: OS X ใช้ BSD sedมากกว่า GNU sedดังนั้นอาจมีความแตกต่างเล็กน้อย (และบางอย่างที่ไม่ลึกซึ้งดังนั้น) ในทั้งสอง นี่เป็นความเจ็บปวดอย่างต่อเนื่องหากคุณทำงานกับทั้ง OS X และ * ระวังเครื่อง ฉันมักจะติดตั้ง GNU coreutilsและfindutilsใน OS X และไม่สนใจรุ่น BSD
Telemachus

50
:aไม่ได้ลงทะเบียนก็เป็นป้ายชื่อสาขา มันเป็นเป้าหมายของbคำสั่ง * ซึ่งทำงานเหมือนกับ "goto" การเรียกว่าทะเบียนหมายความว่าคุณสามารถสร้างที่เก็บข้อมูลได้ มี "รีจิสเตอร์" เพียงสองตัวเท่านั้น อันหนึ่งเรียกว่า "พื้นที่พัก" ซึ่งสคริปต์ของคุณไม่ได้ใช้และอีกอันเรียกว่า "พื้นที่รูปแบบ" Nคำสั่งผนวกบรรทัดใหม่และบรรทัดถัดไปของไฟล์ป้อนข้อมูลไปยังพื้นที่รูปแบบ [* คุณสามารถมีป้ายกำกับ & bคำสั่งได้หลายรายการ หากคุณมีbคำสั่งที่ไม่มีอักขระกำกับต่อท้ายคำสั่งจะแยกไปที่ท้ายสคริปต์เพื่ออ่านบรรทัดถัดไปแล้ววนซ้ำอีกครั้ง]
หยุดชั่วคราวจนกว่าจะมีประกาศเพิ่มเติม

108
คุณสามารถทำงานนี้ข้ามแพลตฟอร์ม (เช่นบน Mac OS X) โดยแยกรันคำสั่งมากกว่าแยกกับจุดคู่กึ่ง: sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
Benjie

74
ทำไมไม่มีใครแสดงความคิดเห็นในสิ่งที่เป็นใบ้นี้ (ไม่ใช่คำตอบของตัวเอง แต่โปรแกรมที่คำตอบที่เสนอเป็นทางออกที่ดีที่สุดสำหรับปัญหาที่ง่ายมาก) Sed ดูเหมือนว่ารถที่มักจะทำงานได้ดี แต่ถ้าคุณต้องการขับรถไปตามถนนที่อยู่ใกล้เคียงวิธีเดียวคือการยกรถด้วยเฮลิคอปเตอร์
Ark-kun

12
Come on folks - 261 upvotes สำหรับคำตอบที่ไม่อาจเข้าใจได้ sed เป็นเครื่องมือที่ยอดเยี่ยมสำหรับ subsitutions อย่างง่าย ๆ ในบรรทัดเดียวสำหรับสิ่งอื่นเพียงแค่ใช้ awk ความเศร้าโศกที่ดี ....
Ed Morton

1711

sedมีวัตถุประสงค์เพื่อใช้กับอินพุตบรรทัด แม้ว่ามันจะสามารถทำสิ่งที่คุณต้องการ


ตัวเลือกที่ดีกว่าที่นี่คือการใช้trคำสั่งดังต่อไปนี้:

tr '\n' ' ' < input_filename

หรือลบอักขระบรรทัดใหม่ทั้งหมด:

tr -d '\n' < input.txt > output.txt

หรือถ้าคุณมีรุ่น GNU (พร้อมตัวเลือกยาว)

tr --delete '\n' < input.txt > output.txt

88
Sed เป็นไลน์ตามดังนั้นจึงยากที่จะเข้าใจการขึ้นบรรทัดใหม่
Alexander Gladysh

191
sed ทำงานบน "สตรีม" ของอินพุต แต่มันเข้าใจในส่วนที่คั่นด้วยบรรทัดใหม่ มันเป็นเครื่องมือยูนิกซ์ซึ่งหมายความว่ามันทำได้ดีมาก สิ่งหนึ่งคือ "ทำงานกับไฟล์ที่ฉลาด" การทำอย่างอื่นจะยากและเสี่ยงต่อการถูกรถ คุณธรรมของเรื่องราวคือเลือกเครื่องมือที่เหมาะสม คำถามของคุณมากมายดูเหมือนจะอยู่ในรูปแบบ "ฉันจะทำให้เครื่องมือนี้ทำสิ่งที่ไม่เคยตั้งใจทำได้อย่างไร" คำถามเหล่านั้นน่าสนใจ แต่ถ้าพวกเขามาในการแก้ปัญหาจริงคุณอาจทำผิด
dmckee --- ผู้ดูแลอดีตลูกแมว

7
@JBBrown trเป็นอัญมณีที่ถูกมองข้ามสำหรับการสร้างท่อส่ง
dmckee --- ผู้ดูแลอดีตแมว

70
tr ดีมาก แต่คุณสามารถแทนที่บรรทัดใหม่ด้วยอักขระเดียวเท่านั้น คุณต้องใช้เครื่องมืออื่นหากคุณต้องการแทนที่บรรทัดใหม่ด้วยสตริง
Eddy

21
@Eddy - ฉันใช้ tr เพื่อแทนที่บรรทัดใหม่ด้วยอักขระที่ไม่ปรากฏในข้อความ (ฉันใช้ backtick) จากนั้นกด sed เพื่อแทนที่ backtick ด้วยสตริงที่ฉันต้องการใช้
rjohnston

494

คำตอบที่รวดเร็ว

sed ':a;N;$!ba;s/\n/ /g' file
  1. : a สร้างป้ายกำกับ 'a'
  2. ยังไม่มีการ ผนวกบรรทัดถัดไปกับพื้นที่รูปแบบ
  3. $! ถ้าไม่ใช่บรรทัดสุดท้าย , ba สาขา (ไปที่) ป้ายกำกับ 'a'
  4. s แทน , / \ n / regex สำหรับสายใหม่ , / / ด้วยช่องว่าง , / g การแข่งขันทั่วโลก (หลายครั้งตามที่มันสามารถ)

sed จะวนซ้ำไปตามขั้นตอนที่ 1 ถึง 3 จนกว่าจะถึงบรรทัดสุดท้ายรับทุกบรรทัดพอดีในพื้นที่รูปแบบที่ sed จะแทนที่อักขระทั้งหมด \ n


ทางเลือก

ทางเลือกทั้งหมดต่างจากsedไม่จำเป็นต้องไปถึงบรรทัดสุดท้ายเพื่อเริ่มต้นกระบวนการ

ด้วยทุบตีช้า

while read line; do printf "%s" "$line "; done < file

ด้วยperl , ความเร็วเหมือนsed

perl -p -e 's/\n/ /' file

ด้วยtr , เร็วกว่าsed , สามารถแทนที่ด้วยอักขระหนึ่งตัวเท่านั้น

tr '\n' ' ' < file

มีวาง , TRเหมือนความเร็วสามารถแทนที่โดยตัวละครตัวหนึ่งเท่านั้น

paste -s -d ' ' file

ด้วยawk , ความเร็วเหมือนTR

awk 1 ORS=' ' file

ทางเลือกอื่น ๆ เช่น"echo $ (<file)"นั้นช้าใช้งานได้กับไฟล์ขนาดเล็กเท่านั้นและจำเป็นต้องประมวลผลไฟล์ทั้งหมดเพื่อเริ่มต้นกระบวนการ


คำตอบที่ยาวจากคำถามที่พบบ่อย sed 5.10

5.10 เหตุใดฉันจึงไม่สามารถจับคู่หรือลบบรรทัดใหม่โดยใช้
ลำดับ\ n ยกเว้น เหตุใดฉันจึงไม่สามารถจับคู่ 2 บรรทัดขึ้นไปโดยใช้ \ n ได้

\ n จะไม่ตรงกับบรรทัดใหม่ที่ท้ายบรรทัดเนื่องจากการขึ้น
บรรทัดใหม่จะถูกตัดออกเสมอก่อนที่จะวางบรรทัดลงใน
พื้นที่รูปแบบ ในการรับ 2 บรรทัดขึ้นไปในพื้นที่รูปแบบให้ใช้
คำสั่ง 'N' หรือสิ่งที่คล้ายกัน (เช่น 'H; ... ; g;')

Sed ทำงานเช่นนี้: Sed อ่านครั้งละหนึ่งบรรทัดตัดการขึ้น
บรรทัดใหม่วางสิ่งที่เหลือไว้ในพื้นที่รูปแบบที่
สคริปต์ sed สามารถแก้ไขหรือเปลี่ยนแปลงและเมื่อพื้นที่รูปแบบ
ถูกพิมพ์ผนวกบรรทัดใหม่เพื่อ stdout (หรือไฟล์) หาก
พื้นที่รูปแบบถูกลบทั้งหมดหรือบางส่วนด้วย 'd' หรือ 'D'
บรรทัดใหม่จะไม่ถูกเพิ่มในกรณีดังกล่าว ดังนั้นสคริปต์เช่น

  sed 's/\n//' file       # to delete newlines from each line             
  sed 's/\n/foo\n/' file  # to add a word to the end of each line         

จะไม่ทำงานเนื่องจากการขึ้นบรรทัดใหม่ต่อท้ายจะถูกลบออกก่อน
ที่บรรทัดจะใส่ในพื้นที่รูปแบบ หากต้องการทำงานด้านบนให้
ใช้หนึ่งในสคริปต์เหล่านี้แทน:

  tr -d '\n' < file              # use tr to delete newlines              
  sed ':a;N;$!ba;s/\n//g' file   # GNU sed to delete newlines             
  sed 's/$/ foo/' file           # add "foo" to end of each line          

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

เพื่อให้ตรงกับบล็อกของสองบรรทัดขึ้นไปมี 3 ตัวเลือกพื้นฐาน:
(1) ใช้คำสั่ง 'N' เพื่อเพิ่มบรรทัดถัดไปในพื้นที่รูปแบบ;
(2) ใช้คำสั่ง 'H' อย่างน้อยสองครั้งเพื่อต่อท้ายบรรทัดปัจจุบัน
ไปยังพื้นที่พักสายแล้วดึงสายจากพื้นที่พัก
ด้วย x, g หรือ G หรือ (3) ใช้ช่วงที่อยู่ (ดูหัวข้อ 3.3 ด้านบน)
เพื่อจับคู่บรรทัดระหว่างที่อยู่ที่ระบุสองแห่ง

ตัวเลือก (1) และ (2) จะใส่ \ n ลงในช่องว่างรูปแบบซึ่ง
สามารถแก้ไขได้ตามต้องการ ('s / ABC \ nXYZ / ตัวอักษร / g') ตัวอย่างหนึ่ง
ของการใช้ 'N' ลบบล็อกของสายปรากฏในส่วน 4.13
( "ฉันจะลบบล็อกของวิธีเฉพาะสายติดต่อกัน?")
ตัวอย่างนี้สามารถแก้ไขได้โดยการเปลี่ยนคำสั่งลบเป็นอย่าง
อื่นเช่น 'p' (พิมพ์), 'i' (แทรก), 'c' (เปลี่ยน), 'a' (ผนวก)
หรือ 's' (ทดแทน) .

Choice (3) จะไม่ใส่ \ n เข้าไปในพื้นที่รูปแบบ แต่มันไม่
ตรงกับบล็อกของสายติดต่อกันดังนั้นจึงอาจเป็นไปได้ว่าคุณไม่
จำเป็นต้อง \ n เพื่อค้นหาสิ่งที่คุณกำลังมองหา ตั้งแต่ GNU sed
เวอร์ชัน 3.02.80 ตอนนี้รองรับไวยากรณ์นี้:

  sed '/start/,+4d'  # to delete "start" plus the next 4 lines,           

นอกจากที่อยู่แบบดั้งเดิม '/ จากที่นี่ /, / ถึงที่นั่น / {... }'
อาจเป็นไปได้ที่จะหลีกเลี่ยงการใช้ \ n โดยสิ้นเชิง


6
trเป็นความคิดที่ดีและความครอบคลุมโดยรวมของคุณทำให้เป็นคำตอบที่มีคุณภาพสูงสุด
ใหม่ Alexandria

1
+1 สำหรับการใช้ ( ยูทิลิตี้มาตรฐาน ) paste... และอื่น ๆ ทั้งหมด!
Totor


4
ส่วนที่ดีที่สุดเกี่ยวกับคำตอบนี้คือ "คำตอบยาว" อธิบายได้อย่างชัดเจนว่าคำสั่งทำงานอย่างไรและทำไม
pdwalker

3
นี่อาจเป็นประโยชน์ที่สุดของคำตอบหลายพันคำตอบที่ฉันได้อ่านใน stackexchange ฉันต้องการจับคู่อักขระหลายตัวข้ามบรรทัด ไม่มีตัวอย่างก่อนหน้านี้ที่ครอบคลุมหลายบรรทัดและ tr ไม่สามารถจัดการการจับคู่อักขระได้หลายรายการ Perl ดูดี แต่ใช้งานไม่ได้ตามที่ฉันคาดไว้ ฉันจะโหวตคำตอบนี้หลายครั้งถ้าทำได้
อันยิ่งใหญ่

225

ทางเลือก awk ที่สั้นกว่า:

awk 1 ORS=' '

คำอธิบาย

โปรแกรม awk ถูกสร้างขึ้นจากกฎซึ่งประกอบด้วยบล็อกโค้ดแบบมีเงื่อนไขเช่น:

condition { code-block }

{ print $0 }หากบล็อกรหัสถูกละไว้เป็นค่าเริ่มต้นที่มีการใช้: ดังนั้นการ1ตีความจะเป็นเงื่อนไขที่แท้จริงและprint $0ถูกดำเนินการสำหรับแต่ละบรรทัด

เมื่อawkอ่านอินพุตมันจะแยกมันออกเป็นเร็กคอร์ดตามค่าของRS(ตัวคั่นเร็กคอร์ด) ซึ่งโดยดีฟอลต์คือบรรทัดใหม่ดังนั้นawkโดยดีฟอลต์จะแยกวิเคราะห์อินพุตบรรทัดที่ชาญฉลาด การแยกยังเกี่ยวข้องกับการลอกออกRSจากบันทึกข้อมูล

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


5
ฉันชอบโซลูชันที่เรียบง่ายมากซึ่งสามารถอ่านได้มากกว่าคนอื่น ๆ
Fedir RYKHTIK

8
ถ้ามันสมเหตุสมผลมากกว่านี้สามารถเขียนได้อย่างมีประสิทธิภาพเป็น: awk 'BEGIN { ORS=" " } { print $0 } END { print "\n"} ' file.txt(เพิ่มบรรทัดใหม่ที่สิ้นสุดเพียงเพื่อแสดงให้เห็นถึงการเริ่มต้น / สิ้นสุด); "1" จะประเมินเป็นtrue(ประมวลผลบรรทัด) และprint(พิมพ์บรรทัด) เงื่อนไขยังอาจจะเพิ่มการแสดงออกนี้เช่นเดียวที่ทำงานอยู่บนเส้นตรงกับรูปแบบ: awk 'BEGIN { ORS=" " } /pattern/ { print $0 } END { print "\n"} '
ไมเคิล

2
คุณสามารถทำได้มากกว่านี้ง่ายๆ: codeawk 'ORS = ""' file.txtcode
Udi

เมื่อใช้ awk แบบนี้โชคไม่ดีที่ฟีดบรรทัดสุดท้ายในไฟล์จะถูกลบเช่นกัน ดูคำตอบของ Patrick Dark ด้านบนเกี่ยวกับการใช้ 'tr' ใน subshell เช่น `cat file | echo $ (tr "\ 012" "") `ซึ่งทำกลอุบาย ดี
เบอร์นีไรเตอร์

143

gnu sed มีตัวเลือก-zสำหรับบันทึกที่คั่นด้วย null (บรรทัด) คุณสามารถโทร:

sed -z 's/\n/ /g'

4
แม้ว่าอินพุตจะมีโมฆะ แต่ก็จะถูกเก็บไว้เป็นตัวคั่นระเบียน
Toby Speight

6
สิ่งนี้จะไม่โหลดอินพุตทั้งหมดหากไม่มีโมฆะหรือไม่ ในกรณีนี้การประมวลผลไฟล์หลายกิกะไบต์อาจมีข้อผิดพลาด
Ruslan

3
@ Ruslan ใช่มันโหลดอินพุตทั้งหมด วิธีนี้ไม่ใช่วิธีที่ดีสำหรับไฟล์ที่มีหลายกิกะไบต์
JJoao

7
นี่เป็นคำตอบที่ดีที่สุดอย่างจริงจัง การแสดงออกอื่นมีความผิดเพี้ยนเกินกว่าจะจำได้ @JJoao -u, --unbufferedคุณสามารถใช้มันด้วย manผู้วิเศษฯ : "โหลดจำนวนน้อยที่สุดของข้อมูลจากแฟ้มใส่และล้างบัฟเฟอร์ส่งออกบ่อยขึ้น"
not2qubit

ดังนั้น. มาก. นี้.
sjas

85

Perlรุ่นทำงานในรูปแบบที่คุณคาดหวัง

perl -i -p -e 's/\n//' file

ตามที่ระบุไว้ในความคิดเห็นมันเป็นที่น่าสังเกตว่าการแก้ไขนี้ในสถานที่ -i.bakจะให้การสำรองข้อมูลไฟล์ต้นฉบับแก่คุณก่อนที่จะทำการแทนที่ในกรณีที่นิพจน์ปกติของคุณไม่ฉลาดเท่าที่คุณคิด


23
โปรดอย่างน้อยพูดถึงว่า-iได้โดยไม่ต้องต่อท้ายทำให้ไม่มีการสำรองข้อมูล -i.bakปกป้องคุณจากความผิดพลาดที่ง่ายและน่าเกลียด (พูดลืมพิมพ์-pและ zeroing out ไฟล์)
Telemachus

6
@ Telemachus: มันเป็นประเด็นที่ยุติธรรม แต่ก็สามารถโต้เถียงได้ทั้งสองทาง เหตุผลหลักที่ฉันไม่ได้พูดถึงคือตัวอย่างที่ไม่ดีในคำถามของ OP ไม่ได้ทำการสำรองข้อมูลดังนั้นจึงดูเหมือนว่าไม่จำเป็น เหตุผลอื่นคือฉันไม่เคยใช้ฟังก์ชั่นการสำรองข้อมูลจริง ๆ (ฉันพบว่าการสำรองข้อมูลอัตโนมัติน่ารำคาญจริง ๆ ) ดังนั้นฉันมักจะลืมมันอยู่ที่นั่น เหตุผลที่สามคือทำให้บรรทัดคำสั่งของฉันยาวขึ้นสี่ตัวอักษร สำหรับดีขึ้นหรือแย่ลง (อาจแย่ลง) ฉันชอบความกระชับ ฉันรู้ว่าคุณไม่เห็นด้วย ฉันจะพยายามทำให้ดีที่สุดเพื่อจำเตือนเกี่ยวกับการสำรองข้อมูลในอนาคต
ire_and_curses

6
@Ire_and_curses: จริงๆแล้วคุณเพิ่งโต้แย้งที่ดีสำหรับการละเว้นฉัน นั่นคือคุณมีเหตุผลสำหรับการเลือกของคุณและไม่ว่าฉันจะเห็นด้วยกับตัวเลือกหรือไม่ฉันก็เคารพอย่างนั้น ฉันไม่แน่ใจว่าทำไมทั้งหมด แต่ฉันได้รับการฉีกขาดเกี่ยวกับสิ่งนี้เมื่อเร็ว ๆ นี้ ( -iธงใน Perl โดยไม่ต้องต่อท้าย) ฉันแน่ใจว่าฉันจะหาสิ่งที่จะครอบงำเกี่ยวกับเร็วพอ :)
Telemachus

มันโชคร้ายจริงๆที่มันไม่สามารถใช้งานได้กับ stdin โดยการระบุ-ชื่อไฟล์ มีวิธีทำเช่นนั้นหรือไม่? นั่นเป็นวิธีการเดินทางของฉันที่ไม่ต้องกังวลเกี่ยวกับการแก้ไขไฟล์โดยใช้ขั้นตอนที่ขึ้นต้นด้วย cat
Steven Lu

@StevenLu Perl จะอ่านจาก STDIN ตามค่าเริ่มต้นหากไม่มีชื่อไฟล์ ดังนั้นคุณสามารถทำเช่นperl -i -p -e 's/\n//' < infile > outfile
ire_and_curses

44

ใครต้องการsedบ้าง นี่คือbashวิธี:

cat test.txt |  while read line; do echo -n "$line "; done

2
ปกติแล้วฉันใช้คำตอบสูงสุด แต่เมื่อ piping / dev / urandom ผ่านมัน sed จะไม่พิมพ์จนกว่า EOF และ ^ C ไม่ใช่ EOF โซลูชันนี้พิมพ์ทุกครั้งที่เห็นบรรทัดใหม่ สิ่งที่ฉันต้องการ! ขอบคุณ!
Vasiliy Sharapov

1
แล้วทำไมไม่: echo -n `cat days.txt` จากโพสต์นี้
โทนี่

9
@Tony เพราะ backticks เลิกใช้แล้วและแมวใช้งานซ้ำซ้อน ;-) ใช้: echo $ (<days.txt)
seumasmac

10
โดยไม่ต้องใช้cat: while read line; do echo -n "$line "; done < test.txt. อาจมีประโยชน์หาก sub-shell เป็นปัญหา
Carlo Cannas

5
echo $(<file)บีบพื้นที่สีขาวทั้งหมดให้เป็นพื้นที่เดียวไม่ใช่แค่ขึ้นบรรทัดใหม่: สิ่งนี้นอกเหนือไปจากสิ่งที่ OP ขอ
เกล็นแจ็คแมน

27

เพื่อแทนที่บรรทัดใหม่ทั้งหมดด้วยช่องว่างโดยใช้ awk โดยไม่ต้องอ่านไฟล์ทั้งหมดในหน่วยความจำ:

awk '{printf "%s ", $0}' inputfile

หากคุณต้องการขึ้นบรรทัดใหม่:

awk '{printf "%s ", $0} END {printf "\n"}' inputfile

คุณสามารถใช้อักขระอื่นนอกเหนือจากช่องว่าง:

awk '{printf "%s|", $0} END {printf "\n"}' inputfile

END{ print ""}เป็นทางเลือกที่สั้นกว่าสำหรับการขึ้นบรรทัดใหม่
Isaac

22
tr '\n' ' ' 

เป็นคำสั่ง

ง่ายและใช้งานง่าย


14
หรือเพียงแค่tr -d '\n'ถ้าคุณไม่ต้องการเพิ่มช่องว่าง
spuder

21

สามสิ่ง.

  1. tr(หรือcatฯลฯ ) ไม่จำเป็นอย่างแน่นอน (GNU) sedและ (GNU) awkเมื่อรวมกันสามารถทำ 99.9% ของการประมวลผลข้อความใด ๆ ที่คุณต้องการ

  2. สตรีม! = ตามบรรทัด edเป็นตัวแก้ไขบรรทัด sedไม่ใช่. ดูการบรรยายเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับความแตกต่าง คนส่วนใหญ่สับสนที่sedจะใช้สายเพราะโดยปกติแล้วมันไม่โลภมากในการจับคู่รูปแบบสำหรับการจับคู่ SIMPLE - ตัวอย่างเช่นเมื่อทำการค้นหารูปแบบและแทนที่ด้วยอักขระหนึ่งหรือสองตัวโดยค่าเริ่มต้นจะแทนที่เฉพาะในการจับคู่แรก พบ จะไม่มีแม้แต่คำสั่งโกลบอลหากเป็นแบบ line-based แทนที่จะเป็นแบบ STREAM เพราะมันจะทำการประเมินผลครั้งละบรรทัดเท่านั้น ลองใช้ed; คุณจะสังเกตเห็นความแตกต่าง edจะเป็นประโยชน์สวยถ้าคุณต้องการที่จะย้ำกว่าเส้นที่เฉพาะเจาะจง (เช่นใน for-loop) sedแต่ส่วนใหญ่เวลาที่คุณเพิ่งจะต้องการ

  3. ที่ถูกกล่าวว่า

    sed -e '{:q;N;s/\n/ /g;t q}' file
    

    ทำงานได้ดีใน GNU sedเวอร์ชัน 4.2.1 คำสั่งดังกล่าวจะแทนที่บรรทัดใหม่ทั้งหมดด้วยช่องว่าง มันน่าเกลียดและค่อนข้างยุ่งยากในการพิมพ์ แต่มันก็ใช้ได้ดี {}'s สามารถปล่อยออกมาในขณะที่พวกเขากำลังรวมเฉพาะสำหรับเหตุผลที่มีสุขภาพจิตดี


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

การใช้การt qกระโดดแบบมีเงื่อนไขเป็นการทำงานกับรูปแบบเช่นs/\n / /(เพื่อเข้าร่วมทุกบรรทัดที่ขึ้นต้นด้วยช่องว่าง) โดยไม่ต้องอ่านไฟล์ทั้งหมดลงในหน่วยความจำ มีประโยชน์เมื่อแปลงไฟล์หลายเมกะไบต์
ตำรา

บทความที่คุณเชื่อมโยงไม่ได้สะท้อนสิ่งที่คุณพูด
hek2mgl

นี่คือเกือบ 800 ครั้งช้ากว่าคำตอบที่ยอมรับในการป้อนข้อมูลขนาดใหญ่ นี่เป็นเพราะการรันการแทนที่สำหรับทุกบรรทัดบนอินพุตที่ใหญ่ขึ้น
Thor

13

คำตอบด้วย: ฉลาก ...

ฉันจะแทนที่บรรทัดใหม่ (\ n) โดยใช้ sed ได้อย่างไร

... ไม่ทำงานใน freebsd 7.2 บนบรรทัดคำสั่ง:

(echo foo; echo bar) sed ': a; N; $! ba; s / \ n / / g'
sed: 1: ": a; N; $! ba; s / \ n / / g": ป้ายกำกับที่ไม่ได้ใช้ 'a; N; $! ba; s / \ n / / g'
foo
บาร์

แต่ถ้าคุณวางสคริปต์ไว้ในไฟล์หรือใช้ -e เพื่อ "สร้าง" สคริปต์ sed ...

> (echo foo; echo bar) | sed -e: a -e N -e '$! ba' -e 's / \ n / / g'
foo bar

หรือ ...

> cat > x.sed << eof
:a
N
$!ba
s/\n/ /g
eof

> (echo foo; echo bar) | sed -f x.sed
foo bar

บางทีความวุ่นวายใน OS X ก็คล้ายกัน


ชุดของอาร์กิวเมนต์ -e ใช้ได้กับฉันบน windows โดยใช้ MKS! ขอบคุณ!
JamesG

12

โซลูชันที่เข้าใจง่าย

ฉันมีปัญหานี้ ตัวเตะคือฉันต้องการโซลูชันเพื่อทำงานกับ BSD (Mac OS X) และ GNU's (Linux และCygwin ) sedและtr:

$ echo 'foo
bar
baz


foo2
bar2
baz2' \
| tr '\n' '\000' \
| sed 's:\x00\x00.*:\n:g' \
| tr '\000' '\n'

เอาท์พุท:

foo
bar
baz

(มีการขึ้นบรรทัดใหม่)

ใช้งานได้กับ Linux, OS X และ BSD - แม้จะไม่รองรับUTF-8หรือเทอร์มินัลเส็งเคร็ง

  1. ใช้trเพื่อสลับขึ้นบรรทัดใหม่ด้วยอักขระอื่น

    NULL( \000หรือ\x00) ดีเพราะไม่ต้องการการสนับสนุน UTF-8 และไม่น่าจะใช้

  2. ใช้sedเพื่อให้ตรงกับNULL

  3. ใช้trเพื่อสลับบรรทัดใหม่พิเศษหากคุณต้องการ


1
หมายเหตุที่ละเอียดอ่อนเกี่ยวกับระบบการตั้งชื่อ: ตัวละคร\000มักจะถูกเรียกว่าNUL(หนึ่ง L) และNULLโดยทั่วไปจะใช้เมื่อพูดถึงตัวชี้ศูนย์(ใน C / C ++)
sqweek


9

ฉันไม่ใช่ผู้เชี่ยวชาญ แต่ฉันเดาว่าsedคุณต้องเพิ่มบรรทัดถัดไปลงในพื้นที่รูปแบบก่อนโดยใช้ " N" จากส่วน "Multiline Pattern Space" ใน "Advanced sed Commands" ของหนังสือsed & awk (Dale Dougherty และ Arnold Robbins; O'Reilly 1997; หน้า 107 ในหน้าตัวอย่าง ):

คำสั่งหลายบรรทัดถัดไป (N) สร้างพื้นที่รูปแบบหลายบรรทัดโดยการอ่านบรรทัดใหม่ของการป้อนข้อมูลและผนวกเข้ากับเนื้อหาของพื้นที่รูปแบบ เนื้อหาต้นฉบับของพื้นที่รูปแบบและบรรทัดอินพุตใหม่ถูกคั่นด้วยบรรทัดใหม่ อักขระขึ้นบรรทัดใหม่ที่ฝังตัวสามารถจับคู่ในรูปแบบตามลำดับ escape "\ n" ในพื้นที่รูปแบบหลายบรรทัดตัวอักขระ "^" จะจับคู่อักขระตัวแรกของพื้นที่รูปแบบไม่ใช่อักขระที่ตามหลังบรรทัดใหม่ที่ฝังอยู่ ในทำนองเดียวกัน "$" จะจับคู่เฉพาะบรรทัดใหม่สุดท้ายในพื้นที่รูปแบบและไม่ขึ้นบรรทัดใหม่ใด ๆ หลังจากรันคำสั่งถัดไปแล้วการควบคุมจะถูกส่งไปยังคำสั่งที่ตามมาในสคริปต์

จากman sed:

[2addr] N

ผนวกบรรทัดถัดไปของอินพุตเข้ากับพื้นที่รูปแบบโดยใช้อักขระขึ้นบรรทัดใหม่เพื่อแยกวัสดุที่ต่อท้ายออกจากเนื้อหาต้นฉบับ โปรดทราบว่าการเปลี่ยนแปลงหมายเลขบรรทัดปัจจุบัน

ฉันใช้สิ่งนี้เพื่อค้นหาไฟล์บันทึกที่จัดรูปแบบไม่ดี (หลายรายการ) ซึ่งอาจพบสตริงการค้นหาในบรรทัดถัดไป "orphaned"


7

ฉันใช้วิธีไฮบริดเพื่อหลีกเลี่ยงสิ่งขึ้นบรรทัดใหม่โดยใช้ tr เพื่อแทนที่บรรทัดใหม่ด้วยแท็บจากนั้นแทนที่แท็บด้วยสิ่งที่ฉันต้องการ ในกรณีนี้ "
" เนื่องจากฉันพยายามสร้างตัวแบ่ง HTML

echo -e "a\nb\nc\n" |tr '\n' '\t' | sed 's/\t/ <br> /g'`

6

เพื่อตอบสนองต่อโซลูชัน "tr" ด้านบนบน Windows (อาจใช้รุ่น Gnuwin32 ของ tr) โซลูชันที่เสนอ:

tr '\n' ' ' < input

ไม่ทำงานสำหรับฉันมันอาจเกิดข้อผิดพลาดหรือแทนที่ \ nw / '' ด้วยเหตุผลบางอย่าง

การใช้คุณสมบัติอื่นของ tr ตัวเลือก "ลบ" -d ทำงานได้:

tr -d '\n' < input

หรือ '\ r \ n' แทนที่จะเป็น '\ n'


3
ใน Windows tr "\n" " " < inputคุณอาจจำเป็นต้องใช้ เชลล์ Windows (cmd.exe) ไม่ถือว่าเครื่องหมายอัญประกาศเป็นอักขระที่อ้างถึง
Keith Thompson

ไม่ในระบบย่อย Windows 10 Ubuntu คุณต้องใช้tr "\n\r" " " < input.txt > output.txt
user1491819

นี้ทำงานบน Windows 10 โดยใช้ cat SourceFile.txt | tr --delete '\r\n' > OutputFile.txtGnuWin32: หรือแทนที่จะใช้ Gnuwin32 ให้ใช้ Gow (Gnu บน Windows), github.com/bmatzelle/gow/wiki
Alchemistmatt

5

วิธีแก้ปัญหากระสุน ไบนารีข้อมูลที่ปลอดภัยและสอดคล้องกับ POSIX แต่ช้า

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

วิธีการแก้ปัญหาต่อไปนี้หลีกเลี่ยง sed และแทนการแปลงไบต์อินพุตเป็นรหัสฐานแปดและจากนั้นเป็นไบต์อีกครั้ง แต่จะสกัดกั้นรหัสฐานแปด 012 (ขึ้นบรรทัดใหม่) และส่งออกสตริงการแทนที่แทน เท่าที่ฉันสามารถบอกได้ว่าวิธีการแก้ปัญหานั้นเป็นไปตาม POSIX ดังนั้นจึงควรใช้กับแพลตฟอร์มที่หลากหลาย

od -A n -t o1 -v | tr ' \t' '\n\n' | grep . |
  while read x; do [ "0$x" -eq 012 ] && printf '<br>\n' || printf "\\$x"; done

POSIX เอกสารอ้างอิง: ดวลจุดโทษ , ภาษาเชลล์คำสั่ง , od , TR , grep , อ่าน , [ , printf

ทั้งสองread, [และprintfบิวด์อินอย่างน้อย bash, แต่นั่นอาจไม่รับประกันโดย POSIX, ดังนั้นในบางแพลตฟอร์ม, มันอาจเป็นได้ว่าแต่ละอินพุทไบต์จะเริ่มกระบวนการใหม่หนึ่งกระบวนการหรือมากกว่า, ซึ่งจะช้าลง แม้ใน bash โซลูชันนี้มีค่าประมาณ 50 kB / s เท่านั้นดังนั้นจึงไม่เหมาะสำหรับไฟล์ขนาดใหญ่

ทดสอบบน Ubuntu (bash, dash และ busybox), FreeBSD และ OpenBSD


5

ในบางสถานการณ์คุณอาจเปลี่ยนRSไปใช้สายอักขระหรืออักขระอื่น วิธีนี้ \ n สามารถใช้ได้สำหรับ sub / gsub:

$ gawk 'BEGIN {RS="dn" } {gsub("\n"," ") ;print $0 }' file

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

เกี่ยวกับสิ่งที่เพ่งพิศช้า ... และอ่านไฟล์ในหน่วยความจำฉันไม่ทราบเรื่องนี้ แต่สำหรับฉันเพ่งพิศดูเหมือนว่าจะทำงานกับหนึ่งบรรทัดในเวลาและรวดเร็วมาก (ไม่เร็วอย่างที่บางคนอื่น ๆ แต่เวลาในการเขียนและทดสอบนับด้วย)

ฉันประมวลผลข้อมูล MB และแม้กระทั่ง GB และข้อ จำกัด เดียวที่ฉันพบคือขนาดบรรทัด


5

หากคุณโชคร้ายพอที่จะจัดการกับปลายสาย windows คุณจำเป็นต้องลบ\rและ\n

tr '[\r\n]' ' ' < $input > $output

สิ่งนี้จะแทนที่[ด้วยช่องว่างและ\rด้วยช่องว่างและ\nด้วยช่องว่างและ]ด้วยช่องว่าง tr -d '\r\n' <fileจะลบอักขระ\rหรือ\nอักขระใด ๆแต่นั่นก็ไม่ใช่สิ่งที่ถูกถาม tr -d '\r' <fileจะลบ\rอักขระใด ๆ(ไม่ว่าพวกเขาจะอยู่ติดกัน\n) ซึ่งอาจใกล้เคียงกับการใช้งานได้ดีและค่อนข้างถูกต้องสำหรับความต้องการของ OP (ยังคงถือว่าคุณtrเข้าใจเครื่องหมายแบ็กสแลชนี้)
tripleee

4

คุณสามารถใช้xargs- มันจะแทนที่\nด้วยช่องว่างโดยค่าเริ่มต้น

อย่างไรก็ตามจะมีปัญหาหากข้อมูลของคุณมีกรณีใด ๆunterminated quoteเช่นหากเครื่องหมายคำพูดในบรรทัดที่ระบุไม่ตรงกัน


xargs จัดการบรรทัดสุดท้ายได้อย่างดี:
AAAfarmclub

4

ค้นหาและแทนที่ด้วยการอนุญาตให้ \ n

sed -ie -z 's/Marker\n/# Marker Comment\nMarker\n/g' myfile.txt

มาร์กเกอร์

กลายเป็น

# เครื่องหมายแสดงความคิดเห็น

มาร์กเกอร์


4

ทำไมฉันไม่หาวิธีแก้ปัญหาง่ายๆด้วยawk?

awk '{printf $0}' file

printf จะพิมพ์ทุกบรรทัดโดยไม่ขึ้นบรรทัดใหม่หากคุณต้องการแยกบรรทัดต้นฉบับด้วยช่องว่างหรืออื่น ๆ :

awk '{printf $0 " "}' file

echo "1\n2\n3" | awk '{printf $0}'มันใช้งานได้สำหรับฉัน @ edi9999
Itachi

คุณขอโทษฉันลืมfใน printf
edi9999

นี่เป็นวิธีการเดียวที่ทำงานให้ฉันภายในทุบตีคอมไพล์สำหรับ windows
Plato

3

บน Mac OS X (ใช้ FreeBSD sed):

# replace each newline with a space
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g; ta'
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g' -e ta


3

ใช้ Awk:

awk "BEGIN { o=\"\" }  { o=o \" \" \$0 }  END { print o; }"

2
คุณไม่จำเป็นต้องหลีกเลี่ยงเครื่องหมายคำพูดและเครื่องหมายดอลลาร์หากคุณเปลี่ยนเครื่องหมายภายนอกเป็นเครื่องหมายคำพูดเดี่ยว ตัวอักษร "o" มักจะถือว่าเป็นตัวเลือกที่ไม่ดีเป็นชื่อตัวแปรเนื่องจากอาจสับสนกับหลัก "0" คุณไม่จำเป็นต้องกำหนดค่าเริ่มต้นให้กับตัวแปรมันจะใช้ค่าเริ่มต้นเป็นสตริงว่าง awk '{s = s sp $0; sp = " "} END {print s}'แต่ถ้าคุณไม่ต้องการให้พื้นที่ชั้นนำภายนอก: อย่างไรก็ตามดูคำตอบของฉันสำหรับวิธีการใช้ awk โดยไม่ต้องอ่านไฟล์ทั้งหมดลงในหน่วยความจำ
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

โปรดตรวจสอบคำตอบของ Thorแทน มันเป็นวิธีที่มีประสิทธิภาพมากขึ้นอ่านได้และดีขึ้นโดยทุกวิธีการเปรียบเทียบวิธีนี้ (แม้ว่าจะใช้งานได้)!
mschilli

เพื่อนฉันเข้าใจแล้ว ไม่จำเป็นต้องถูมันในหน้าของฉัน :-) คำตอบของ ธ ​​อร์เป็นวิธีที่อยู่บนหน้าต่อไป (ซึ่งถูกต้อง) ดังนั้นสิ่งที่คุณสนใจ?
kralyk

3

วิธีที่ฉันชอบเป็นพิเศษคือการต่อท้ายไฟล์ทั้งหมดในพื้นที่พักไว้และแทนที่บรรทัดใหม่ทั้งหมดที่ท้ายไฟล์:

$ (echo foo; echo bar) | sed -n 'H;${x;s/\n//g;p;}'
foobar

อย่างไรก็ตามมีบางคนบอกว่าพื้นที่สำหรับเก็บสามารถ จำกัด ได้ในการใช้งานบางอย่าง


1
การแทนที่ด้วยสตริงว่างในคำตอบของคุณจะปกปิดความจริงที่ว่าการใช้ H เพื่อผนวกเข้ากับพื้นที่พักเสมอหมายความว่าพื้นที่พักจะเริ่มต้นด้วยบรรทัดใหม่ เพื่อหลีกเลี่ยงปัญหานี้คุณต้องใช้1h;2,$H;${x;s/\n/x/g;p}
Jeff

3

แทนที่บรรทัดใหม่ด้วยสตริงใด ๆ และแทนที่บรรทัดใหม่ล่าสุดด้วย

trโซลูชันที่บริสุทธิ์สามารถแทนที่ด้วยอักขระเดียวเท่านั้นและsedโซลูชันที่แท้จริงจะไม่แทนที่บรรทัดใหม่สุดท้ายของอินพุต วิธีแก้ไขปัญหาต่อไปนี้แก้ไขปัญหาเหล่านี้และดูเหมือนว่าจะปลอดภัยสำหรับข้อมูลไบนารี (แม้จะมีโลแคล UTF-8):

printf '1\n2\n3\n' |
  sed 's/%/%p/g;s/@/%a/g' | tr '\n' @ | sed 's/@/<br>/g;s/%a/@/g;s/%p/%/g'

ผลลัพธ์:

1<br>2<br>3<br>

สิ่งนี้ไม่ดีเพราะมันจะสร้างผลลัพธ์ที่ไม่ต้องการในอินพุตที่มี@
Steven Lu

@StevenLu: ไม่@ในการป้อนข้อมูลเป็น OK มันถูกหลบหนีไป%aและกลับมาอีกครั้ง วิธีแก้ปัญหาอาจไม่สอดคล้องกับ POSIX อย่างสมบูรณ์แม้ว่า (NULL-bytes ไม่ได้รับอนุญาตจึงไม่ดีสำหรับข้อมูลไบนารีและทุกบรรทัดต้องลงท้ายด้วย newline เพื่อให้trเอาต์พุตไม่ถูกต้องจริงๆ)
Håkon A. Hjortland

อา. ฉันเห็นคุณซ่อมมันแล้ว ค่อนข้างซับซ้อนสำหรับสิ่งที่ควรจะใช้งานง่าย แต่ทำงานได้ดี
Steven Lu

3

มันเป็นsedแนะนำว่าใหม่เส้นหลัง "ปกติ" เปลี่ยนตัว อันดับแรกมันตัดขอบอักขระขึ้นบรรทัดใหม่จากนั้นประมวลผลตามคำแนะนำของคุณจากนั้นจะแนะนำบรรทัดใหม่

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

PROMPT~$ cat <<EOF |sed 's/$/===/g'
first line
second line
3rd line
EOF

first line===
second line===
3rd line===
PROMPT~$

ในการแทนที่อักขระขึ้นบรรทัดใหม่ด้วยสตริงคุณสามารถใช้trตามที่ชี้ไว้ก่อนหน้านี้เพื่อแทนที่อักขระขึ้นบรรทัดใหม่ด้วย "อักขระพิเศษ" แล้วใช้sedเพื่อแทนที่อักขระพิเศษนั้นด้วยสตริงที่คุณต้องการ .

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

PROMPT~$ cat <<EOF | tr '\n' $'\x01'|sed -e 's/\x01/===/g'
first line
second line
3rd line
EOF

first line===second line===3rd line===PROMPT~$

3

คุณสามารถใช้วิธีนี้ได้เช่นกัน

sed 'x;G;1!h;s/\n/ /g;$!d'

คำอธิบาย

x   - which is used to exchange the data from both space (pattern and hold).
G   - which is used to append the data from hold space to pattern space.
h   - which is used to copy the pattern space to hold space.
1!h - During first line won't copy pattern space to hold space due to \n is
      available in pattern space.
$!d - Clear the pattern space every time before getting next line until the
      last line.

โฟลว์:
เมื่อบรรทัดแรกได้รับจากอินพุตการแลกเปลี่ยนจะเกิดขึ้นดังนั้น 1 จะถือพื้นที่และ \ n มาถึงพื้นที่รูปแบบจากนั้นผนวกพื้นที่เก็บข้อมูลกับพื้นที่รูปแบบจากนั้นทำการทดแทนและลบพื้นที่รูปแบบ
ในระหว่างการแลกเปลี่ยนบรรทัดที่สองทำ 2 ไปพักพื้นที่และ 1 มาถึงพื้นที่รูปแบบจากนั้นGผนวกพื้นที่พักไว้ในพื้นที่รูปแบบแล้วhคัดลอกรูปแบบไปที่มันและทำทดแทนและถูกแทนที่ การดำเนินการนี้จะดำเนินต่อไปจนกว่าจะถึง eof แล้วพิมพ์ผลลัพธ์ที่แน่นอน


แต่จะเตือนว่าผลในการecho 'Y' | sed 'x;G;1!h;s/\n/X/g;$!d' XY
Spooky

3

อีกวิธีหนึ่งของGNU sedซึ่งเกือบจะเหมือนกับคำตอบของZsolt Botykaiแต่คำสั่งนี้ใช้คำสั่ง( ทับศัพท์ ) ที่sedไม่ค่อยได้ใช้บ่อยนักซึ่งจะช่วยประหยัดหนึ่งไบต์ของโค้ด (การต่อท้าย):yg

sed ':a;N;$!ba;y/\n/ /'

หนึ่งจะหวังว่าyจะทำงานได้เร็วกว่าs(บางทีอาจเป็นเพราะtrความเร็ว 20x เร็วกว่า) แต่ในGNU sed v4.2.2 yเป็นเรื่องเกี่ยวกับ4%sช้ากว่า


รุ่นBSD แบบพกพาเพิ่มเติมsed:

sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'

2
ด้วย BSD sed yจะเร็วขึ้น 15% ดูคำตอบนี้สำหรับตัวอย่างการทำงาน
Thor

นอกจากนี้ด้วยคำสั่ง BSD sed จำเป็นต้องยกเลิกหลังจากป้ายกำกับดังนั้นsed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'จะเป็นวิธีที่จะไป
ghoti
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.