vi โดยย่อ

ปรับปรุงครั้งที่ 1 : 50-09-06

กลับมาช่วยกันซ่อมสร้างบทความกันใหม่นะครับ

สรุปคำสั่ง vi โดยย่อ จาก vi manual

การเลื่อนเคอร์เซอร์

  • h, [<-] = ไปซ้าย
  • l, [SPACEBAR] = ไปขวา
  • k, - = ขี้นบน
  • j, + = ลงล่าง

  • b = ซ้าย 1 คำ
  • w = ขวา 1 คำ

  • 0, ^ = ต้นบรรทัด
  • $ = ท้ายบรรทัด

  • ( = ต้นประโยค
  • ) = ท้ายประโยค

  • { = ต้นย่อหน้า
  • } = ท้ายย่อหน้า

  • [RETURN] = บรรทัดต่อไป

  • H = ต้นหน้า
  • M = กลางหน้า
  • L = ท้ายหน้า

  • G = ท้ายไฟล์

  • ^f = เลื่อนลง 1 หน้า
  • ^b = เลื่อนขึ้น 1 หน้า
  • ^d = เลื่อนลงครึ่งหน้า
  • ^u = เลื่อนขึ้นครึ่งหน้า

ใช้ร่วมกับตัวเลข

  • n? = ปฏิบัติคำสั่ง ? จำนวน n ครั้ง
     3j = ลง 3 บรรทัด
     4h = ซ้าย 4 อักขระ
     5w = ขวา 5 คำ
     1G = บรรทัดแรกของไฟล์
    

การยกเลิกสถานะ

เนื่องจาก vi เป็นเอดิเตอร์แบบมีสถานะ จึงต้องมีการเข้าสู่สถานะต่าง ๆ และการออกจากสถานะนั้น ๆ

  • [ESC], ^[ = ยกเลิกสถานะอื่นๆ เพื่อกลับสู่สถานะปกติ

สถานะการลบ

  • x = ลบ 1 อักขระ

  • dw = ลบตั้งแต่เคอร์เซอร์จนถึงต้นคำหน้า
  • d$, D = ลบตั้งแต่เคอร์เซอร์จนถึงท้ายบรรทัด
  • dL = ลบตั้งแต่บรรทัดปัจจุบันจนถึงท้ายจอภาพ
  • dh = ลบ 1 อักขระก่อนถึงเคอร์เซอร์
  • dd = ลบบรรทัดปัจจุบัน
  • dG = ลบจากบรรทัดปัจจุบันจนถึงท้ายไฟล์
  • d1G = ลบจากบรรทัดปัจจุบันจนถึงต้นไฟล์
  • J = join เชื่อมบรรทัดถัดไปกับบรรทัดปัจจุบัน

ใช้ร่วมกับตัวเลข

   d3w, 3dw = ลบ 3 คำ
   5dd, 4dj = ลบ 5 บรรทัด จากบรรทัดปัจจุบัน 
               ( 4dj=ลบบรรทัดปัจจุบัน และอีก 4 บรรทัดถัดไป )
   4dk = ลบบรรทัดปัจจุบัน และอีก 4 บรรทัดก่อนหน้า
   5Gdd = ลบบรรทัดที่ 5

การแทรกและแก้ไข

สถานะ : a=append=เติม, i=insert=แทรก, c=change=เปลี่ยน, o=open=เปิด, s=substitute=แทน, r=replace=แทนที่

  • i = แทรกอักษรก่อนเคอร์เซอร์
  • a = แทรกอักษรหลังเคอร์เซอร์
  • I = แทรกอักษรต้นบรรทัด
  • A = แทรกอักษรท้ายบรรทัด

  • o = แทรกบรรทัดว่างต่อจากบรรทัดปัจจุบัน
  • O = แทรกบรรทัดว่างก่อนหน้าบรรทัดปัจจุบัน

  • c$, C = เปลี่ยน = ลบเนื้อความตั้งแต่เคอร์เซอร์ไปจนท้ายบรรทัด พร้อมทั้งเตรียมเพิ่มข้อความ
  • cw = ลบ 1 คำ พร้อมทั้งเตรียมเพิ่มข้อความ
  • cc = ลบทั้งบรรทัด พร้อมทั้งเตรียมเพิ่มข้อความ

  • r = แทนที่ 1 อักขระใต้เคอร์เซอร์
  • R = แทนที่อักขระตั้งแต่ใต้เคอร์เซอร์เป็นต้นไป จนกว่าจะออกจากสถานะนี้

  • s = ลบ 1 อักขระ พร้อมทั้งเตรียมเพิ่มข้อความ
  • S = ลบบรรทัดปัจจุบัน พร้อมทั้งเตรียมเพิ่มข้อความ

ใช้ร่วมกับตัวเลข

   5inewtext = แทรก newtext 5 ครั้ง
   5rg = แทนที่ด้วย g 5 ตัว

หมวดค้นหา

  • / = ค้นหา
  • ? = ค้นหาย้อนกลับ
  • n, / = ค้นซ้ำ นับจากบรรทัดปัจจุบันลงไป

  • N = ค้นซ้ำ นับจากบรรทัดปัจจุบันขึ้นไป
  • N, ?[ENTER] = ค้นซ้ำย้อนกลับ นับจากตำแหน่งปัจจุบันขึ้นไป

คัดลอก, แปะ, ยกเลิก, ทำซ้ำ

  • yy, Y = คัดลอกบรรทัดปัจจุบัน
  • yw = คัดลอกคำปัจจุบัน

  • p = แปะลง หลังจากเคอร์เซอร์
  • P = แปะลง ก่อนหน้าเคอร์เซอร์

* การลบ จะมีการเก็บสิ่งที่ลบไว้ในความจำ ดังนั้น ถ้ามีคำสั่งแปะตามมา สิ่งที่แปะลงมาก็คือสิ่งที่เพิ่งถูกลบไปนั่นเอง

  • ddp = ลบบรรทัดปัจจุบัน และแปะลงทันที = การสลับบรรทัด
  • xp = การสลับตัวอักษร

ใช้ร่วมกับตัวเลข

   y4w = คัดลอก 4 คำ

ใช้ร่วมกับคำสั่งพิเศษ+ตัวเลข

  • :?t? = คัดลอกจากบรรทัด ? ไปบรรทัด ?
  • :?m? = ย้ายจากบรรทัด ? ไปบรรทัด ?
    :t5 = คัดลอกจากบรรทัดปัจจุบัน ไปบรรทัด 5
    :m5 = ย้ายจากบรรทัดปัจจุบัน ไปบรรทัด 5
    :9t5 = คัดลอกจากบรรทัด 9 ไปบรรทัด 5
    
    :9m5 = ย้ายจากบรรทัด 9 ไปบรรทัด 5
    
  • u = ยกเลิกการแก้ไขครั้งล่าสุด
  • U = ยกเลิกการแก้ไขทั้งหมด ในบรรทัดปัจจุบัน
  • . = ทำซ้ำการแก้ไขครั้งล่าสุด

คำสั่งพิเศษ

  • :wq, :x, ZZ = จัดเก็บและออกจากโปรแกรม

  • :w = จัดเก็บ
  • :w FILENAME = จัดเก็บลงในไฟล์ FILENAME
  • :w! = จัดเก็บ โดยละเลยข้อกำหนดของระบบ
  • :w! FILENAME = เขียนทับ FILENAME โดยไม่เตือน

  • :q = ออกจากโปรแกรม
  • :q! = ออกจากโปรแกรม โดยไม่เตือน

  • :! COMMAND = สั่งรัน COMMAND ของเชลล์

  • :e FILENAME = เปิดไฟล์ FILENAME
  • :e! FILENAME = เปิดไฟล์ FILENAME โดยไม่เตือนถึงการจัดเก็บไฟล์เก่า

  • :r FILENAME = แทรกไฟล์ FILENAME ตรงตำแหน่งเคอร์เซอร์ปัจจุบัน

  • :f, ^g = แสดงแถบสถานะ ตรงด่านล่างซ้ายมือ
  • :h, :help = แสดงความช่วยเหลือ (ออกจากหมวดช่วยเหลือด้วย :q )
  • :h COMMAND, :help COMMAND = แสดงความช่วยเหลือสำหรับคำสั่ง COMMAND
  • :se COMMAND, :set COMMAND = ตั้งค่าคำสั่ง COMMAND

ค้นหาและแทนที่

ยืมโครงสร้างมาจากคำสั่ง sed (stream editor) ในระบบยูนิกซ์

  • :1,$ s/old/new/g = ค้นหา old แทนที่ด้วย new เริ่มตั้งแต่ 1=ต้นไฟล์ จนถึง $=จบไฟล์ โดยกำหนดค่าการค้นเป็น g=global

เพิ่มเติม

ในการใช้ vi แบบใช้งานจริงจัง มักนิยมใช้ vim มากกว่า vi ซึ่งเก่ามากแล้ว (สำหรับเดเบียนคือแพกเกจ vim-full ) คำสั่งติดตั้งคือ

$ sudo aptitude install vim-full

และสั่งให้เป็น editor ปริยาย

$ sudo update-alternatives --config editor

เลือก /usr/bin/vim.full

ข้อเขียนเพิ่มเติมนี้จะอ้างอิงจากคู่มือของ vim เป็นหลักครับ

มีชุดคำสั่งพิเศษที่น่านำมาใช้ (นำมาจากคอมเมนต์ของคุณ tonkla ด้านล่างครับ) คือ

  • :set tabstop=4 = กำหนดแท็บเป็น 4 ช่องว่าง
  • :set expandtab = กำหนดให้ใช้ช่องว่างแทนแท็บ (จำนวนช่องว่างกำหนดจากคำสั่ง tabstop
  • :set autoindent = กำหนดย่อหน้าอัตโนมัติ
  • :set nu! = แสดงหมายเลขบรรทัด
  • :syntax on = แสดงโครงสร้างไฟล์เป็นสี

ซึ่งเราสามารถนำมาเขียนเป็นไฟล์ทรัพยากรที่กำหนดเป็นค่าปริยายในการใช้งาน คือไฟล์ vimrc ถ้าให้มีผลต่อผู้ใช้ทุกคนคือไฟล์ /etc/vim/vimrc.local หรือถ้าให้มีผลต่อเราคนเดียวก็คือไฟล์ ~/.vimrc

การเขียนคำสั่งในไฟล์ vimrc ก็เขียนเหมือนกับการใช้คำสั่งพิเศษทุกประการ เพียงแต่ไม่ต้องใส่ colon(:) เท่านั้น เช่น

$ vi ~/.vimrc
set tabstop=4
set expandtab
set autoindent
set smartindent
set nu!
syntax on

คำสั่งพิเศษอื่น ๆ ขอท่านผู้อ่านช่วยเขียนเพิ่มเติมเป็นคอมเมนต์ให้ด้วยครับ

Topic: 

Comments

ขอบคุณมากๆ เลยครับ

ขอบคุณมากๆ เลยครับ ช่วงนี้ผมยิ่งใช้ vi บ่อยอยู่แล้ว กำลังคิดจะหาข้อมูล แบบนี้พอดี
เพราะที่ใช้อยู่ส่วนใหญ่ทำได้แค่ dd ,pageup,pagedown,backspace,spacebar,arrow key

เพิ่มเติมครับ
- การยกเลิกสถานะสามารถใช้ Ctrl+[ ได้อีกทางหนึ่ง ผมว่าแบบนี้สะดวกกว่า ESC แฮะ
- J สำหรับ join 2 บรรทัดเข้าด้วยกัน (ใช้ร่วมกับ n? ได้เหมือนคำสั่งอื่นๆ)
- :?string สำหรับค้นหาย้อนกลับ (มีค่าเท่ากับ :/string แล้วกด N)
- สำหรับ :tn (คัดลอก), :mn (ย้าย) นั้น หากทำจากบนลงล่าง n จะใช้ค่าบรรทัดปกติ แต่ถ้าทำจากล่างขึ้นบน ต้องใช้ n=n-1 .. ผมเข้าใจอะไรผิดไหมครับ?

- :set tabstop=4 สำหรับเว้นระยะห่างของการกดแท็บ 4 ช่องต่อแท็บ
- :set shiftwidth=4 (ไม่ทราบ)
- :set autoindent ย่อหน้าอัตโนมัติ ใช้เขียนโปรแกรมได้ดีทีเดียว
- :set smartindent (ไม่ทราบ)
- :set nu! สำหรับแสดงหมายเลขบรรทัด
- :syntax on สำหรับสั่ง highlight syntax

ขอเพิ่มเติมนอกเรื่องอีกสักหน่อย
- Ctrl+u สำหรับ undo การพิมพ์ใน terminal มีประโยชน์อย่างยิ่งตอนพิมพ์รหัสผ่าน แล้วไม่แน่ใจว่าพิมพ์ถูกหรือเปล่า
- เปลี่ยนภาษาชั่วคราวใน gnome ที่นิยมใช้คือกด Alt ขวาค้างไว้ โดยต้องไปตั้งค่าใน gnome keyboard preferences ก่อน ... ลองใช้ดูครับ มีประโยชน์มาก
- copy&paste ใน gnome (หรือ X?) คัดลอกโดยใช้เม้าส์ highlight เลือกข้อความ แล้ววางด้วยการกดเม้าส์ปุ่มกลาง มีประโยชน์ตอนอยู่บน Firefox, IceWeasel แล้วขี้เกียจกดเปลี่ยนแป้นพิมพ์ให้เป็นภาษาอังกฤษก่อน

ขอบคุณมากครับ ขออนุญาตนำไปปรับปรุงเนื้อความหลักด้วยนะครับ

เกร็ดเสริมครับ
ผมชอบเขียนสคริปต์ไพธอนในการทำงานเล็ก ๆ น้อย ๆ ซึ่งไพธอนกำหนดให้ใช้ช่องว่าง 4 อักขระแทนแท็บ
ผมเลยเขียนคำสั่งเพิ่มคือคำสั่ง
:set expandtab
เวลาเรากดแท็บ vim จะสร้างช่องว่าง 4 ช่องแทน

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

ถ้าจะแปลงกลับ คือแปลงช่องว่าง 4 ช่องกลับเป็นแท็บ ใช้คำสั่ง
:1,$ s/ /^I/g
(ระหว่าง / เคาะ 4 วรรค และกด [TAB] ตามลำดับ)

เพิ่มเติมสำหรับ gvim ครับ ... วิธีการคอมเมนต์แบบบล็อค

- กด ^q หรือ ^Q เพื่อเข้าสู่โหมด visual block หรือจะใช้เม้าส์ลากก็ไม่ว่ากัน
- กด j หรือ ปุ่มลง เพื่อเลือกบรรทัดที่ต้องการจะทำคอมเมนต์ (ใช้ n? ก็สะดวกดี)
- กด I เพื่อเพิ่มข้อความในคอลัมน์แรกของแต่ละบรรทัด
- กด # หรือ //
- กด Esc หรือ ^[

สำหรับวิธีลบคอมเมนต์ก็ทำคล้ายๆ กัน คือหลังจากเลือกบรรทัดที่ต้องการแล้ว ให้กด x

เยี่ยมเลย
ผมใช้ vim-full บน terminal ใช้ปุ่ม ^v สำหรับ Visual Block ครับ
(ใช้ vim นี่ ฝึกไอคิวไปในตัวนะครับ :)

ยอดไปเลยครับ ผมใช้ vim บน gnome-terminal พอกด ^q มันจะปิดหน้า terminal ทิ้งไป
เลยใช้วิธีนี้ได้กับ gvim อย่างเดียว พอรู้การใช้ ^v แล้ว มีประโยชน์ขึ้นเยอะเลยครับ

feature โปรดใน vi สำหรับผมคือการแทนที่ด้วย sed pattern ครับ

สมมุติว่ามี text ที่แบ่งบรรทัดมา อยากจะแทรก HTML tag ให้เป็น bullet

ant
bat
cat

สั่ง:

:%s/.*/<li> & <\/li>/

& ใน substution pattern ใช้แทน text ที่ match ดังนั้น จะกลายเป็น:

<li> ant </li>
<li> bat </li>
<li> cat </li>

จากนั้นก็เพิ่ม <ul> กับ </ul> เอา

ยิ่งถ้าเจอกรณีซับซ้อน เช่น มีข้อความแบบนี้:

ant = มด
bat = ค้างคาว
cat = แมว

แล้วต้องการสลับภาษาไทยกับอังกฤษ แล้วเพิ่ม <li> tag ด้วย ก็สั่ง:

:%s/\(.*\) = \(.*\)/<li> \2 = \1 <\/li>/

รูปแบบ "\(pattern\)" ใน search pattern ใช้เก็บ text ที่ match กับ pattern ลงบัฟเฟอร์ไว้ ซึ่งสามารถอ้างถึงตามลำดับการเก็บได้ด้วยรูป "\1", "\2, ... ใน substitution pattern

จากคำสั่งข้างบนคำสั่งเดียว กลายเป็น:

<li> มด = ant </li>
<li> ค้างคาว = bat </li>
<li> แมว = cat </li>

เป็นตัวอย่างสั้น ๆ แต่คงพอให้เห็นภาพ ว่าถ้าเจอ text file ยาว ๆ แล้วต้อง edit บ่อย ๆ ทำไมผมจะไม่ติด vi งอมแงม :)

หมายเหตุ: ทั้งหมดที่กล่าวมา ใช้กับ vi มาตรฐานได้

ิเพิ่มเติมเรื่องการย่อหน้า

ใช้ >> แทนการกด Tab
ใช้ << แทนการกด Shift + Tab

สามารถใช้ร่วมกับตัวเลขได้ เช่น 4>> คือให้ 4 บรรทัดนับจากเคอเซอร์ Tab ไปทางขวา

หากต้องการให้ช่อง Tab กว้างขึ้น ให้กำหนดที่ค่า shift width โดยใช้คำสั่ง :set sw=n

ทั้งนี้ทั้งนั้นค่า tabstop, expendtab ก็มีผลต่อรูปแบบการ Tab ด้วย ลองเล่นดูครับ สนุกและใช้ประโยชน์ได้

ปกติ vim จะตีความข้อมูลด้วยค่า locale ของเครื่อง เช่น ถ้าตั้งค่า locale เป็น utf-8 ด้วยคำสั่ง

# dpkg-reconfigure locales

แล้วตั้งเป็น th_TH.utf8 เวลาเราเรียกใช้ vim เราจะสามารถใช้งานภาษาไทยที่เข้ารหัสเป็น utf8 ได้โดยทันที

ปัญหาคือ ถ้าเรามีบางไฟล์ที่เข้ารหัสข้อมูลด้วยรหัสอื่น เช่น tis620 เราจะไม่สามารถใช้งานภาษาไทยได้
วิธีแก้คือ

  1. สั่งงาน vim ด้วยตัวแปร env LANG เป็นค่า locale ที่ต้องการ
    # LANG=th_TH.tis620 vim FILENAME
  2. ตั้งค่าตัวแปร encoding เป็น thai
    :set enc=thai
  3. ตั้งค่าตัวแปร termencoding เป็น utf-8
    :set termencoding=utf-8

ด้วยวิธีนี้ เราสามารถแก้ไขไฟล์ที่เข้ารหัสเป็น tis-620 ได้ครับ

(แต่อาจยังมีปัญหาเรื่องชนิดของ Terminal ไม่รองรับการวางสระของภาษาไทย ผมใช้วิธีพิมพ์ใหม่ทั้งบรรทัด)

ถ้าเราจะทำ code snipped แบบ IDE ตัวอื่นๆเราจะต้องทำอย่างไรครับ เช่น

พิมพ์ว่า sout แล้วกด spacebar มันจะเปลี่ยนตัว sout เป็น System.out.println() อะไรประมาณนี้น่ะครับ

เข้าใจว่า (g)vi(m) ทำไม่ได้ครับ เพราะโดยพื้นฐานแล้วมันคือ text editor ส่วนความสามารถที่ว่ามาเห็นมีแต่ใน IDE ... เข้าใจว่า text editor เจ๋งๆ อย่าง TextMate ก็ยังทำแบบนี้ไม่ได้
หากมีท่านใดทำได้ก็รบกวนแจ้งด้วยนะครับ

TextMate ทำได้ครับ แล้วก็ทำได้ดีด้วยครับ

ซึ่งนอกจาก code snipped แล้ว อีกทั้งยังทำเป็น template ให้เราได้ด้วย แบบว่า มัน generate สร้างเนื้อ code ขึ้นมา แล้วก็ให้เรากรอกตามช่องว่างที่ code มันเว้นไว้ให้ กรอกเสร็จแต่ละช่องก็กด Tab มันก็จะไปช่องต่อไปให้เรากรอกครับ

เจ๋งมากๆเลยครับ TextMate

ไม่ตรงกับที่ถามโดยตรง แต่อาจพอช่วยได้ (ได้ยินมาจากคนอื่นอีกที แต่ตอนนี้ใช้จนติดซะละ) คือ vim จะมี auto-completion คล้าย Emacs โดยพิมพ์ส่วนต้นของคำแล้วกด ^p มันจะไปหาคำที่ขึ้นต้นเหมือนกันที่เคยคีย์มาแล้วในเอกสาร แล้วเติมให้ ถ้ากำกวมก็มีเมนูให้เลือก หรือไม่ก็กด ^p ซ้ำ ไปเรื่อย ๆ จนกว่าจะได้ตัวที่ต้องการ

ช่วยได้มากครับ ตอนเขียนโปรแกรมแล้วขี้เกียจคีย์ชื่อฟังก์ชันเต็ม ๆ เนี่ย กันคีย์ผิดได้ด้วย

แต่นี่ดูเหมือนมีแต่ใน vim นะครับ ไม่มีใน vi มาตรฐาน

จากตัวอย่าง sout เป็น System.out.printf(""); นี่น่าจะใช้คำสั่งย่อนะครับเช่น
:ab sout System.out.printf("
แล้วลองพิมพ์ sout

แต่ถ้าอยากจะได้ snippet จิงๆ ก็มี plugins ชื่อว่า snippetemu ครับ ตาม link ข้างล่าง
http://www.vim.org/scripts/script.php?script_id=1318
ลงเสร็จจะ snippet ที่มีให้ใช้เลยก็เช่น jps, jtc
จะเพิ่มเองอีกก็ได้นะครับ
เอาให้สุดยอดไปเลย จะได้ไม่ต้องอิจฉา textmate เค้าอีก
:)

ขอบคุณมากครับ

ขอบคุณมากครับ

ขอบคุณครับ คำสั่งต่างๆใน vim พอรู้มาบ้างแล้ว

แต่ชอบ auto-completion มากเลย เพิ่งทราบ ^p เจ๋งมาก

Creative Commons License ลิขสิทธิ์ของบทความเป็นของเจ้าของบทความแต่ละชิ้น
ผลงานนี้ ใช้สัญญาอนุญาตของครีเอทีฟคอมมอนส์แบบ แสดงที่มา-อนุญาตแบบเดียวกัน 3.0 ที่ยังไม่ได้ปรับแก้