วิธีแทนที่อักขระด้วยบรรทัดใหม่ใน Vim


1967

ฉันพยายามแทนที่แต่ละ,ไฟล์ในบรรทัดปัจจุบันด้วยบรรทัดใหม่:

:%s/,/\n/g 

แต่จะแทรกสิ่งที่ดูเหมือนเป็น^@แทนที่จะขึ้นบรรทัดใหม่จริง ไฟล์ไม่ได้อยู่ในโหมด DOS หรืออะไรก็ตาม

ฉันควรทำอย่างไรดี?

หากคุณอยากรู้อยากเห็นฉันตรวจสอบคำถามเพราะเหตุใด \ ra newline สำหรับ Vim เช่นกัน


2
Stack Overflow เป็นเว็บไซต์สำหรับคำถามเกี่ยวกับการเขียนโปรแกรมและการพัฒนา คำถามนี้ดูเหมือนจะไม่ได้อยู่ที่หัวข้อเพราะไม่เกี่ยวกับการเขียนโปรแกรมหรือการพัฒนา ดูหัวข้อใดบ้างที่ฉันสามารถถามเกี่ยวกับที่นี่ในศูนย์ช่วยเหลือ บางทีผู้ใช้ระดับสูงหรือUnix & Linux Stack Exchangeอาจเป็นสถานที่ที่ดีกว่าที่จะถาม
jww

5
@ jww คำถามนี้อายุ 10 ปี ... ดูเหมือนว่าจะแก่เกินไปที่จะโยกย้าย มีคำถามมากมายเช่นนี้เช่น: stackoverflow.com/questions/10175812/…
Vinko Vrsalovic

14
@jww เป็นกลุ่มเป็นเครื่องมือที่ใช้กันทั่วไปสำหรับโปรแกรมเมอร์และคำถามเกี่ยวกับเครื่องมือที่ใช้กันทั่วไปสำหรับโปรแกรมเมอร์ในหัวข้อในกองมากเกิน แม้ว่าจะเห็นได้ชัดว่านี่เหมาะสำหรับVi และ Vimมากกว่า
user202729

คำตอบ:


2565

ใช้แทน\r\n

การแทนที่ด้วยการ\nแทรกอักขระ null ลงในข้อความ \rจะได้รับการขึ้นบรรทัดใหม่ใช้ เมื่อค้นหาบรรทัดใหม่คุณยังคงใช้งาน\nอยู่ ความไม่สมดุลนี้เกิดจากความจริงที่ว่า\nและ\r ทำสิ่งต่าง ๆ เล็กน้อย :

\nตรงกับจุดสิ้นสุดของบรรทัด (ขึ้นบรรทัดใหม่) ในขณะที่\rตรงกับการคืนค่าขนส่ง ในทางกลับกันในการแทนที่\nแทรกอักขระ null ในขณะที่\rแทรกขึ้นบรรทัดใหม่ (แม่นยำยิ่งขึ้นก็ถือว่าเป็นอินพุต<CR>) นี่คือตัวอย่างเล็ก ๆ ที่ไม่โต้ตอบเพื่อแสดงสิ่งนี้โดยใช้คุณสมบัติบรรทัดคำสั่ง Vim (กล่าวอีกนัยหนึ่งคุณสามารถคัดลอกและวางสิ่งต่อไปนี้ในเทอร์มินัลเพื่อเรียกใช้) xxdแสดง hexdump ของไฟล์ผลลัพธ์

echo bar > test
(echo 'Before:'; xxd test) > output.txt
vim test '+s/b/\n/' '+s/a/\r/' +wq
(echo 'After:'; xxd test) >> output.txt
more output.txt
Before:
0000000: 6261 720a                                bar.
After:
0000000: 000a 720a                                ..r.

กล่าวอีกนัยหนึ่ง\nได้แทรกไบต์ 0x00 ลงในข้อความ \rได้แทรกไบต์ 0x0a


127
/ r ถือเป็นการกดปุ่ม Enter / Return มันทำงานได้บนทุกแพลตฟอร์ม
Luka Marinko


14
ฉันหวังว่ามันใช้งานได้สำหรับคลาสสิก vi บน AIX v6.1 \rไม่ทำงานเช่นนี้ แต่คุณสามารถกดCtrl-V Enterแทนการพิมพ์\rและใช้งานได้
eksortso

3
ฉันไปงานปาร์ตี้สาย หาก\rส่วนแทรก<CR>และ\nส่วนแทรกเป็นโมฆะฉันจะแทนที่สิ่งใดด้วยการคืนค่าขนส่งได้อย่างไร
Mr. Llama

2
@SunnyRaj คุณแน่ใจเกี่ยวกับประวัติของ CR และ LF หรือไม่? ฉันรู้สึกประทับใจว่าเดิมที LF ย้ายกระดาษไปข้างหน้าหนึ่งแถว แต่ไม่ได้เลื่อนหัวพิมพ์และ CR ก็เลื่อนหัวพิมพ์ แต่ไม่ขยับกระดาษ ดังนั้นหากระบบปฏิบัติการของคุณไม่แปลงอินพุตก่อนพิมพ์คุณไม่สามารถใช้เพียงแค่ LF หรือ CR เพื่อให้ได้ผลลัพธ์ที่ถูกต้อง MS DOS ใช้ข้อมูลเครื่องพิมพ์แบบดิบเป็นรูปแบบไฟล์ข้อความ Mac OS ใช้ CR และแปลงจากรูปแบบไฟล์ดิบเป็นเครื่องพิมพ์และ UNIX ใช้ LF และแปลงจากรูปแบบไฟล์ดิบเป็นเครื่องพิมพ์
Mikko Rantalainen

210

นี่คือเคล็ดลับ:

ก่อนอื่นให้ตั้งค่าเซสชัน Vi (m) ของคุณเพื่ออนุญาตการจับคู่รูปแบบกับอักขระพิเศษ (เช่น: ขึ้นบรรทัดใหม่) อาจคุ้มที่จะวางบรรทัดนี้ไว้ในไฟล์. vimrc หรือ. exrc ของคุณ:

:set magic

ถัดไปทำ:

:s/,/,^M/g

เพื่อให้ได้^Mตัวอักษรที่พิมพ์Ctrl+ และตีV Enterภายใต้ Windows ทำCtrl+ ,Q Enterวิธีเดียวที่ฉันสามารถจำสิ่งเหล่านี้ได้โดยการจำความรู้สึกของพวกเขาที่ทำได้น้อย:

ตอบ: อักขระควบคุมที่แย่ที่สุดในการใช้เพื่อเป็นตัวแทนของการขึ้นบรรทัดใหม่คืออะไร

B: อย่างใดอย่างหนึ่งq(เพราะมันมักจะหมายถึง "ออก") หรือvเพราะมันเป็นเรื่องง่ายมากที่จะพิมพ์Ctrl+ Cโดยไม่ได้ตั้งใจและฆ่าบรรณาธิการ

ตอบ: ทำให้เป็นอย่างนั้น


9
ฉันใช้ GVim บน Windows และฉันต้องไม่:set magic(มันไม่ได้อยู่ในของฉัน ~ / _vimrc อย่างใดอย่างหนึ่ง) ctrl-qหรือ ง่าย ๆctrl-vตามมาด้วยการสร้าง^Mตัวละครสำหรับฉันได้ดี
Chris Phillips

5
Cv ไม่ได้หมายถึงการขึ้นบรรทัดใหม่ มันเป็นคำสั่ง "หลบหนีตัวอักษรตัวต่อไป" ฉันไม่ได้รู้ว่า Cv เป็นตัวช่วยจำสำหรับอะไร แต่ก็มีเหตุผลที่มันไม่ได้ทำแผนที่ทางใจกับการขึ้นบรรทัดใหม่
จิมสจ๊วต

27
Ctrl-v เป็นตัวช่วยจำสำหรับ "verbatim" - ie escape คีย์ถัดไปที่กดไปยังคีย์โค้ด / อักขระ "verbatim" ใน Windows มันเป็นการวาง: เพื่อให้ทุกอย่างคุ้นเคย Ctrl-Q ใช้สำหรับ "(un) Quote" อาจจะ ค่อนข้างโง่แล้ว - แต่คุณสามารถใช้มันในไฟล์ไบนารี - เช่นเพื่อค้นหา Ctrl-A ถึง Ctrl-Z (Ascii 1-26 ฉันเดา)
Tomasz Gandor

1
Ctrl-Cไม่ได้ฆ่าโปรแกรมแก้ไขแม้ว่าจริง ๆ แล้วมันสามารถยกเลิกคุณกลับสู่โหมดปกติได้ Ctrl-Vหมายถึงคำต่อคำและCtrl-Qหมายความว่ามีคนทำผิดพลาดในการโหลด$VIMRUNTIME/mswin.vimไฟล์การกำหนดค่า คุณไม่ต้องการ mswin เพียงใช้ vimrc ของคุณเองแทน
00dani

ว้าว ---- มันวิเศษมาก ฉันเคยทำมาsed -n l จนถึงตอนนี้ เป็นการดีที่จะรู้ว่าสิ่งเดียวกันนี้สามารถเกิดขึ้นได้ด้วยCtrl-vในกลุ่ม
Arpit

98

ในไวยากรณ์s/foo/bar, \rและ\nมีความหมายที่แตกต่างกันขึ้นอยู่กับบริบท


สั้น:

สำหรับfoo:

\ n = newline (LF บน Linux / Mac, CR + LF บน Windows)
\ r = carriage return (CR)

สำหรับbar:

\ r = is newline
\ n = null ไบต์

อีกต่อไป (พร้อมหมายเลข ASCII):

NUL= 0x00 = 0 = Ctrl+ @
LF= 0x0A = 10 = Ctrl+ J
CR= 0x0D = 13 = Ctrl+M

นี่คือรายการที่ตัวควบคุม ASCII ใส่พวกเขาในการเป็นกลุ่มผ่านCtrl+ V, +Ctrl---key---

ในทุบตีหรืออื่น ๆ เปลือกหอย Unix / Linux เพียงพิมพ์+Ctrl---key---

ลองCtrl+ Mใน Bash มันเหมือนกับการกดปุ่มEnterเพราะเชลล์รู้ว่ามันหมายถึงอะไรแม้ว่าระบบ Linux จะใช้ไลน์ฟีดสำหรับการกำหนดบรรทัด

ในการแทรกตัวอักษรใน bash การเติมพวกเขาด้วยCtrl+ Vจะใช้งานได้

ลองใน Bash:

echo ^[[33;1mcolored.^[[0mnot colored.

นี้ใช้ลำดับหนี ANSI ใส่สอง^['s ผ่านCtrl+ ,VEsc

คุณอาจลองCtrl+ V, Ctrl+ M, Enterซึ่งจะทำให้คุณนี้:

bash: $'\r': command not found

จำ\rจากข้างบน? :>

นี้ASCII ตัวควบคุมรายการจะแตกต่างจากที่สมบูรณ์ตารางสัญลักษณ์ ASCIIในการที่ตัวควบคุมซึ่งจะแทรกเข้าไปในคอนโซล / pseudoterminal / กลุ่มผ่านCtrlคีย์ (ฮ่าฮ่า) สามารถพบได้มี

โดยที่ใน C และภาษาอื่น ๆ ส่วนใหญ่คุณมักจะใช้รหัสฐานแปดเพื่อแสดง 'อักขระ' เหล่านี้

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


TL; DR

โดยปกติfoo= \nและ=bar\r


1
ดังนั้นฉันจึงรู้สึกทึ่งว่าคุณจะแทนที่ตัวละครด้วยการคืนรถได้อย่างไร
codehot

2
@codeshot :s/x/^M/gควรทำอย่างไร ใส่^Mผ่านทางตามด้วยctrl-v ctrl-m
sjas

3
ขอบคุณ sjas คุณจะรู้ว่าคำถามนี้เป็นหนึ่งในสิ่งที่แปลกประหลาดที่สุดตลอดกาล 1008 คะแนนโหวตสำหรับคำตอบที่โดยทั่วไปบอกว่าไม่มีอะไรมากไปกว่า "เสียงเรียกเข้าทำในสิ่งที่คุณพบนั่นเพราะเสียงเรียกเข้าทำในสิ่งที่คุณพบอย่าลืมว่าเสียงเรียกเข้าดังกล่าวทำในสิ่งที่คุณพบ" ฉันหวังว่าจะค้นหารหัสสั้น ๆ ของตัวละครที่น่าสนใจในรูปแบบการแทนที่และเหตุผลของความแปลกประหลาดดังนั้นมันจึงง่ายต่อการจดจำและทำนายความแปลกประหลาดอื่น ๆ ที่คล้ายกัน นั่นจะได้รับการโหวตของฉัน
codehot

@codeshot รายการของอักขระควบคุม ASCII อาจช่วยคุณได้ ดูcs.tut.fi/~jkorpela/chars/c0.htmlสำหรับการอ้างอิงเพิ่มเติม ฉันจะอัปเดตคำตอบเพื่อรวมสองลิงก์
sjas

55

คุณต้องใช้:

:%s/,/^M/g

เพื่อให้ได้^Mตัวอักษรที่กดCtrl+ ตามด้วยvEnter


4
ฉันต้องทำ <Cv> <Cm> เพื่อให้ได้ตัวละคร ^ M
Jezen Thomas


24

ด้วยความที่เป็นกลุ่มบน Windows, การใช้งานCtrl+ Qในสถานที่ของ+CtrlV


16

นี่คือคำตอบที่ดีที่สุดสำหรับวิธีที่ฉันคิด แต่มันจะดีกว่าในตาราง:

ทำไมต้องขึ้นบรรทัดใหม่สำหรับ Vim

ดังนั้น rewording:

คุณต้องใช้\rเพื่อใช้การป้อนบรรทัด (ASCII 0x0A, การขึ้นบรรทัดใหม่ของ Unix) ในการแทนที่ regex แต่นั่นเป็นเรื่องแปลกสำหรับการแทนที่ - โดยปกติแล้วคุณควรคาดหวังว่าจะใช้\nสำหรับการป้อนบรรทัดและ\rเพื่อให้การขึ้นบรรทัดใหม่

นี่เป็นเพราะกลุ่มที่ใช้\nในการเปลี่ยนเพื่อหมายถึงอักขระ NIL (ASCII 0x00) คุณอาจจะคาดหวัง NIL จะได้รับ\0แทนพ้น\nสำหรับการใช้งานปกติสำหรับอาหารเส้น แต่\0แล้วมีความหมายในการเปลี่ยน regex \nดังนั้นมันก็เปลี่ยนไป ดังนั้นจากนั้นจะเพิ่มขึ้นอีกเพื่อเปลี่ยนบรรทัดใหม่จาก\nเป็น\r(ซึ่งในรูปแบบ regex คืออักขระ carriage return, ASCII 0x0D)

ตัวละคร | รหัส ASCII | ตัวแทน C | การแข่งขัน Regex การแทนที่ Regex
------------------------- + ------------ + ----------- ------- + ------------- + ------------------------
ไม่มี 0x00 | \ 0 | \ 0 | \ n
ขึ้นบรรทัดใหม่ (Unix ขึ้นบรรทัดใหม่) 0x0a | \ n | \ n | \ r
คืนสินค้า 0x0d | \ r | \ r | <ไม่รู้จัก>

NB: ^M( Ctrl+ V Ctrl+ Mบน Linux) แทรกบรรทัดใหม่เมื่อใช้ในการแทนที่ regex แทนที่จะส่งคืนค่าขนส่งตามที่ผู้อื่นได้แนะนำ (ฉันเพิ่งลอง)

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


11

จากคราสที่^Mตัวละครสามารถฝังตัวอยู่ในแนวเดียวกันและคุณต้องการที่จะแปลงให้เป็นบรรทัดใหม่

:s/\r/\r/g

8

แต่ถ้ามีใครจะมาแทนที่แล้วสิ่งต่อไปนี้ทำงาน:

:%s/\n/\r\|\-\r/g

ในข้างต้นทุกบรรทัดถัดไปจะถูกแทนที่ด้วยบรรทัดถัดไปและจากนั้น|-และบรรทัดใหม่อีกครั้ง ใช้ในตารางวิกิ

หากข้อความดังต่อไปนี้:

line1
line2
line3

มันเปลี่ยนเป็น

line1
|-
line2
|-
line3

7

ถ้าคุณต้องการทำทั้งไฟล์มันก็แนะนำให้ฉันว่าคุณสามารถลองจากบรรทัดคำสั่ง:

sed 's/\\n/\n/g' file > newfile

1
โปรดทราบว่าสิ่งนี้ต้องใช้ GNU sed ลองprintf 'foo\\nbar\n' | sed 's/\\n/\n/g'ดูว่ามันจะทำงานบนระบบของคุณ (ให้เครดิตกับคนดีของ #bash บน freenode สำหรับคำแนะนำนี้)
Evan Donovan


5

นี่คือคำตอบที่เหมาะกับฉัน จากผู้ชายคนนี้:

---- quoting ใช้เครื่องมือแก้ไข vi เพื่อแทรกอักขระขึ้นบรรทัดใหม่เพื่อแทนที่


อย่างอื่นที่ฉันต้องทำและจำไม่ได้แล้วต้องค้นหา

ใน vi เพื่อแทรกอักขระบรรทัดใหม่ในการค้นหาและแทนที่ให้ทำดังต่อไปนี้:

:%s/look_for/replace_with^M/g

คำสั่งด้านบนจะแทนที่อินสแตนซ์ทั้งหมดของ "look_for" ด้วย "replace_with \ n" (ด้วย \ n หมายถึงการขึ้นบรรทัดใหม่)

ในการรับ“ ^ M” ให้ป้อนคีย์ผสมCtrl+ Vและหลังจากนั้น (ปล่อยแป้นทั้งหมด) กดEnterปุ่ม


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