跳轉到內容

學習 vi 編輯器/詳細資訊

來自華夏公益教科書,開放的書籍,開放的世界

學習 vi 編輯器: 熟悉基本任務使工作更輕鬆高階任務詳細資訊Vi 克隆 (Vim基本導航模式技巧和竅門程式設計師需要了解的有用內容增強 VimVim 在 Windows 上VimL 指令碼語言, Vile, BB vi)vi 參考

本節描述了 vi 程式本身的一些細節(例如命令列功能)以及其他面向有抱負的 vi 高階使用者的 vi 高階功能。

命令列呼叫

[編輯 | 編輯原始碼]

當然,不同的 vi 克隆有不同的啟動程式(呼叫)方法。然而,通常情況下,vi 的命令列版本共享一組通用的基本命令列選項。以下這些命令列選項和標誌通常可用。此外,vi 可以使用不同的名稱啟動。根據啟動 vi 所使用的名稱,它可能在行為上略有不同,或者載入不同的 vi 克隆。


常見的命令列選項和標誌是

-

或者

-s
抑制。所有互動式使用者反饋都將被抑制(不會寫入終端)。這允許將編輯命令透過管道傳輸到編輯器,並將其用作一種流編輯器。在 Unix 上可能存在更好的流編輯器工具,例如 sed(1)、awk(1) 或 Perl(n)。
注意,"-" 是 Unix 中用來表示標準輸入的常見符號。vi 作者選擇它作為-s的替代方案,以便在透過管道傳輸命令時提供熟悉的外觀。它並不真正意味著“從標準輸入讀取”,因為 vi 本來就那樣做。
-C
cryptography(加密)。vi 會提示使用者輸入金鑰(一種密碼),並使用此金鑰在寫入之前對檔案進行加密。它還會使用此金鑰對使用 vi 開啟的任何檔案進行解密。此功能不受許多克隆支援,並且加密演算法非常弱(它基於 256 個元素的單轉子演算法)。該演算法很容易破解。它與 Unix crypt(1) 命令相容。另請參見-x.
-l
(小寫字母 L) 更改一些預設設定,使其更適合編輯 LISP 原始碼。
-L
(大寫字母 L) 列出在崩潰期間已儲存的所有檔案。請參見-r,也是。
-r filename
在崩潰後恢復檔案 filename。使用-L獲取可以恢復的檔案列表。
-R
只讀。檔案只能檢視,不能寫入。
-S
標籤 未排序。當使用 tag 檔案時,此標誌告訴 vi tag 檔案未排序,因此 vi 將使用較慢的演算法查詢標籤。請參見-t,也是。
-t tag
編輯(開啟)包含給定 tag 的檔案。當然,這需要一個名為 tags 的標籤檔案可用。
-v
以可視模式啟動。僅在編輯器以 ex 而不是 vi 的名稱啟動時才有用。
-V
詳細。透過標準輸入讀取的命令將回顯到標準錯誤。這在編輯器用作流編輯器時進行除錯時非常有用。
-wnumber
視窗大小。將編輯器的行數設定為 number。vi 的行為就好像終端只有 number 行。這在過去使用緩慢的終端或調變解調器線路連線時用來加速操作。
-x
加密。類似於-C。不同之處在於 vi 試圖猜測要開啟的檔案是否需要解密。另一方面,-C在開啟檔案時始終執行解密操作。
+command

或者

-c command
在允許使用者輸入自己的命令之前執行命令 command。最常見的用法是使用它將編輯器定位在檔案中的某個特定行。例如
vi +10 list.txt
將開啟檔案list.txt並將游標定位在第 10 行。另一種常見用法是指定一個模式
vi +/END script.awk
這將開啟檔案script.awk並將游標定位在模式 'END' 的首次出現位置。

如前所述,vi 可以使用不同的名稱啟動(並非所有名稱都可用,具體取決於特定的克隆)

vi
啟動 vi 的常用方法。
view
vi 以只讀模式啟動。
vedit
更改了一些設定以更適合初學者:magic 被清除,showmodenovice 被設定,並且 report 被設定為 1。
ex -v
與直接輸入vi

命令:物件 & 運算子

[編輯 | 編輯原始碼]

到目前為止,本教程只討論了命令,以及命令如何與詞語計數等內容結合使用。例如d2w已被解釋為運算子delete 應用於兩個詞語。注意2w部分。您已經瞭解到這部分指定了運算子應該應用於哪些文字。事實上,2w部分指定了運算子應該應用於哪些文字物件(詞語、行、字元等)。您已經看到相同的物件說明符可以與所有型別的運算子一起使用 - 只要組合有意義。

實際上,vi 命令遵循一個通用模式。命令由運算子和物件組成

   [[count] operator] [[number] object]

這意味著運算子應該在數量物件上執行次數次。幾乎所有部分都是可選的。另外,有些運算子根本不接受物件。這種運算子/操作語法是vi的核心。這就是人們要麼喜歡vi,要麼討厭vi的原因。人們喜歡它,因為它是一個如此簡單的模式。一旦一個人瞭解了幾個運算子(不超過十個),以及幾個物件,就可以在vi中非常高效地工作。那些討厭vi的人 simply 無法理解這個模式,以及命令模式和插入模式之間存在差異的事實。

我們已經告訴過你,像w這樣的命令會移動一個單詞。我們在告訴你這一點時,實際上有點欺騙了。並不存在像w這樣的命令。w是一個物件規範,而不是一個命令。物件規範是在沒有像d這樣的顯式運算子的情況下給出的。在這種情況下,vi 使用隱式預設運算子。而這個運算子是移動

每當你使用沒有運算子的物件規範時,都會使用移動運算子。因此,物件規範會退化為移動命令。以下是所有物件規範的列表和摘要。從邏輯上講,你可以將它們與運算子結合使用,或者在獨立使用時用於四處移動。你已經見過其中的一些了。

段落、節、句子物件

[編輯 | 編輯原始碼]
}
直到下一個段落結束的所有內容。
{
直到上一個段落結束的所有內容。
]]
[直到下一個節結束的所有內容。]
[[
[直到上一個節結束的所有內容。]
)
直到下一個句子結束的所有內容。
(
直到上一個句子結束的所有內容。

行物件

[編輯 | 編輯原始碼]
[數字]G
直到第數字行。如果省略了數字,則為檔案中的最後一行(不是第一行)。第一行可以表示為1G代替。
[數字]H
當前螢幕上第一行之後的數字行。如果未給出數字,則為螢幕上的第一行。
[數字]L
當前螢幕上最後一行之前的數字行。如果未給出數字,則為螢幕上的最後一行。
M
螢幕的中間行。
j
當前行向下移動一行。
k
當前行向上移動一行。
_
(下劃線) 整個當前行。

行內位置

[編輯 | 編輯原始碼]
0
(數字 0). 向後移動到行的第一列。與1|(非0|).
^
向後移動到第一個非空白字元。
$
向前移動到行尾。
[數字] |
當前行的第數字列。如果未給出數字,則使用第 1 列。
t字元
當前行中下一個字元出現之前的位置。
T字元
當前行中下一個字元出現之後的位置。
f字元
當前行中下一個字元出現的位置。
F字元
當前行中上一個字元出現的位置。
;
重複最後一個t, T, f, 或者F這樣的命令。
,
重複最後一個t, T, f, 或者F命令,但在相反方向。
+

或者

<CR>
移動到下一行的第一個非空白字元。
-
移動到上一行的第一個非空白字元。


單詞物件

[編輯 | 編輯原始碼]
w
向前移動到下一個單詞的開頭。
e
向前移動到下一個單詞的結尾。
b
向後移動到上一個單詞的開頭。

字元物件

[編輯 | 編輯原始碼]
h

或者

<BS>
左邊的字元。
l

或者

<SPACE>
(小寫字母 L 或空格) 右邊的字元。


模式匹配物件

[編輯 | 編輯原始碼]
/模式/
向前移動到模式模式的第一個匹配項的開頭。
?模式?
向後移動到模式模式的第一個匹配項的開頭。
<n>
重複最後一個/或者?.
<N>
重複最後一個/或者?在相反方向。
<%>
移動到下一個匹配的 (, {, 或 [。

運算子

[編輯 | 編輯原始碼]

前面列出的物件可以作為運算子的引數。如果未給出運算子,則使用預設的移動運算子。vi 中的運算子數量驚人地少——總共十個。以下是運算子的列表。

需要更好的描述,其中一些將在本模組的後面部分單獨進行描述。

接受物件的的運算子

[編輯 | 編輯原始碼]
c
更改 - 更改所指向的物件。實際上,文字會被輸入的內容替換。
d
刪除 - 刪除所指向的物件。被刪除的文字會被放置到撤銷緩衝區中。
y
貼上 - 將所指向物件的文字複製到緩衝區中。
<
左移 - 物件引數只能是那些指向行的物件縮排和移位
>
右移 - 物件引數只能是那些指向行的物件縮排和移位
!
感嘆號 過濾 - 透過外部程式過濾行。物件只能是那些指向行的物件過濾(存根)

不接受物件的的運算子

[編輯 | 編輯原始碼]

r, s,

x
刪除字元。使用d 運算子刪除字元以外的物件。
~
切換游標位置字元的大小寫。大寫字母將變成小寫字母,小寫字母將變成大寫字母。

特殊運算子形式

[編輯 | 編輯原始碼]

在輸入運算子時,有兩種特殊形式。

  1. 輸入大寫字母,而不是小寫字母。例如Y代替y,以及
  2. 重複該字元。例如yy代替y.

螢幕上的“奇怪”行

[編輯 | 編輯原始碼]

vi 是在終端或調變解調器連線速度很慢的時代編寫的。因此,vi 使用了幾種最佳化技術來限制重繪整個螢幕的需要。在這種情況下,vi 以前會顯示以特殊標記開頭的行。現代 vi 很少需要這種效能最佳化,但它們仍然有顯示這種行的習慣。

使用兩種特殊的標記。

~line

以“~”開頭的行表示該行在檔案末尾之後(不存在)。例如,在空檔案或新檔案中啟動 vi 時,就可以觀察到這種情況。

@line

該行只在螢幕上,不在檔案中。這會發生在刪除行時。如果啟用了換行(預設值),則對於太長而無法在螢幕上一次顯示的所有行也會發生這種情況。

縮排和移位

[編輯 | 編輯原始碼]

vi 支援文字行的自動縮排,還提供手動縮排的命令。這在編輯程式原始碼時很有用。在許多程式語言中,使用縮排以提高原始碼的可讀性是一種常見的慣例。

選項shiftwidth(sw) 決定縮排使用多少空格。例如。

<ESC>:set shiftwidth=4<CR>

或者

<ESC>:set sw=4<CR>

告訴 vi 使用四個空格進行縮排。

選項 [no]autoindent(ai) 告訴 vi 是否使用自動縮排。自動縮排透過以下命令開啟

<ESC>:set autoindent<CR>

或者

<ESC>:set ai<CR>

它透過以下命令關閉

<ESC>:set noautoindent<CR>

或者

<ESC>:set noai<CR>

命令模式

[edit | edit source]

移動行使用 < 和 > 命令。< 將文字向左移動一個shiftwidth(取消縮排),而 > 將文字向右移動一個shiftwidth(縮排)。可以影響的行數以 vi 的典型方式指定。但是,只能使用標識行的 物件,而不能使用標識單詞或單個字元的物件

例如。

>G

將從當前行到檔案結尾的所有行向右移動。

或者

<}

將從當前行到段落結尾的所有行向左移動。當然,移位命令可以與%一起使用,它表示下一個左括號。例如,要將包含當前游標位置的行(直到第一行與匹配的 (、{ 或 [ 相匹配)向左移動一個,可以鍵入

<%

與所有命令一樣,也可以指定行數

[number]<<

或者

<[number]<
移動從當前行開始的number 行,向左移動一個shiftwidth(取消縮排)。如果未給出number,則假定為 1 - 這會導致將當前行向左移動。
[number]>>

或者

>[number]>
移動從當前行開始的number 行,向左移動一個shiftwidth向右移動一個(縮排)。如果未給出number,則假定為 1 - 這會導致將當前行向右移動。

< 和 > 命令也可以與標記一起使用。在這種情況下,對標記的引用放在命令的兩個字元之間

<'m<
將從標記m 到包括當前行的所有行向左移動。
>'m>
將從標記m 到包括當前行的所有行向右移動。

插入模式

[edit | edit source]
^t
向右移動shiftwidth。請注意,使用 <TAB> 鍵而不是^t是一個常見的錯誤。<TAB> 插入一個 Ctrl-I 字元並移動到下一個tabstop 的倍數,而不是shiftwidth。因此,只有當tabstopshiftwidth 設定為相同的值時,<TAB> 才能工作。
由於將tabstop 設定為 8 以外的值不是一個好主意,因此,只有當shiftwidth 也設定為 8 時,才能使用 <TAB> 代替^t進行縮排。
^d
在自動縮排模式下,向後縮排一個shiftwidth。例如,如果自動縮排開啟,並且想要輸入以下文字
if(true) {
    printf("done"); // start sw indent
    return;
} // bracket moved back to the left
將鍵入
if(true) {<CR>
^tprintf("done"); // start sw indent<CR>
return;<CR>
^d} // bracket moved back to the left<CR>

還有一些^d的特殊變體

^^d
(字母^ 後跟 Ctrl-D)。當在新的行上首次鍵入此命令時,所有自動縮排都會被清除(插入點將移動到行的開頭)。然後在下一行繼續自動縮排。
例如,要在使用自動縮排時輸入以下文字
        an indented paragraph
        another line in the indented paragraph
.F roff formating commands have to start at column one with a '.'
        more text in the indented paragraph

將鍵入

^tan indented paragraph<CR>
another line in the indented paragraph<CR>
^^d.F roff formating commands have to start at column one with a '.'<CR>
more text in the indented paragraph<CR>
0^d
(數字0 後跟 Ctrl-D)。清除所有自動縮排(將游標移動到行的開頭),並關閉自動縮排,直到手動縮排文字(使用^t).
例如,要在使用自動縮排時輸入以下文字
     INTEGER FUNCTION FAC(N)
     FAC = 1
     DO 100 I = 2, N
          FAC = I * FAC
C
C PROVIDE LABEL TO END LOOP
C A HINT FOR THOSE GRASSHOPPERS: THIS IS FORTRAN CODE :-)
C
100  CONTINUE
     RETURN
     END
   
將鍵入
<ESC>:set sw=5<CR>
o^tINTEGER FUNCTION FAC(N)<CR>
FAC = 1<CR>
DO 100 I = 2, N<CR>
^tFAC = I * FAC<CR>
0^dC<CR>
C PROVIDE LABEL TO END LOOP<CR>
C A HINT FOR THOSE GRASSHOPPERS: THIS IS FORTRAN CODE :-)<CR>
C<CR>
100  CONTINUE<CR>
^tRETURN<CR>
END<CR>

模型行

[edit | edit source]

模型行是文字檔案中的行,當開啟此類文字檔案時,vi 會對其進行特殊解釋。當modeline (ml)(在某些版本的 vi 中也稱為modelines)選項開啟(例如,在使用者的.exrc檔案中),vi 會掃描每個開啟檔案的首尾五行,以查詢以下形式的文字

unrelated text vi:command: more unrelated text

或者

unrelated text ex:command: more unrelated text

從這些行中獲取每個command 並按使用者鍵入的方式執行。模型行標記前面的任何文字(vi或者ex)或關閉標記後面的任何文字:在模型行解釋中被忽略。這可以用於將模型行放在註釋中,如果它們用於某些程式設計原始碼。

這是一個示例 Java 原始碼檔案。它在第二行和第三行包含模型行,位於 Java 註釋中

/* 
 * vi:set sw=4 ai:
 * vi:set showmatch: 
 */
package gnu.freesoftware; public class Interpreter { public Interpreter() ... ...

當模型行開啟,並且開啟此檔案時,shiftwidth (sw)設定為 4,autoindent (ai)開啟,並且showmatch (sm)選項也會開啟。沒有特別的理由說明為什麼要使用兩個模型行上的兩個set命令,除了演示在首尾五行中找到的所有模型行命令都將被執行,而不僅僅是第一個。

模型行可以用於玩一些實際的玩笑。例如,包含模型行的檔案

vi:q!:

立即關閉編輯器,並且只要模型行開啟,就無法編輯檔案。

如果模型行弄亂了系統檔案,則會變得非常危險。例如,如果 Unix 系統的超級使用者(管理員)打開了模型行,並且被誘騙開啟包含以下模型行的檔案,則重要的 Unix 密碼檔案將被開啟檔案的內容覆蓋

vi:2,$w! /etc/passwd:
root:A shiny new root password:0:0:System Administrator:/:/bin/sh
anotheruser:Another shiny new password:1:0:Just another user:/home/anotheruser:/bin/sh

因此,模型行只能在受控環境中開啟。這很遺憾,因為原則上,檔案能夠為編輯器提供最適合編輯該檔案的配置是一個好主意。

模型行還存在一些其他問題。經典的 vi 版本在找到模型行時始終將檔案的狀態設定為已修改,即使沒有對檔案進行任何編輯。這會迫使使用者使用以下命令退出編輯器:q!而不是:q。如果改為使用ZZ退出,則檔案將被寫入。這會導致像make 這樣的工具認為檔案已更改,即使實際上沒有更改。

.exrc 配置檔案

[edit | edit source]

此模組是一個 存根。您可以透過 修復它 來幫助 Wikibooks。 首先

.exrc 檔案是包含 vi(和 ex)配置資料的檔案。此類檔案中的資料格式是 ex 命令的格式,沒有前導 ':'(列)。通常,.exrc 檔案用於載入一些預設對映(map 和 map! ex 命令)或定義特定預設值。例如,以下 .exrc 檔案將在啟動 vi 時設定自動縮排和 shiftwidth

set ai
set sw=4

通常,.exrc 檔案放置在使用者的 home 目錄中。由於檔名以 '.' 開頭,因此該檔案在類 Unix 作業系統下是隱藏的。也可以在其他目錄中放置 .exrc 檔案。vi 可以讀取從其啟動的當前目錄中的 .exrc 檔案。但是,此功能被認為是一種安全風險,預設情況下已關閉。它被認為是一種風險,因為與模型行所描述的相同的笑話也可以對 .exrc 檔案進行。使用者 home 目錄中的 .exrc 檔案被認為是安全的,因為在正確配置的 Unix 系統上,只有特定使用者應該對其具有寫訪問許可權。

在使用經典的 vi 和 .exrc 檔案時,應該注意三件事

  1. .exrc 檔案不能包含空行。經典的 vi 會因這些行而出現各種神秘的錯誤訊息。
  2. 沒有官方的方式在 .exrc 檔案中放置註釋。但是,從一開始,以下 hack 就被使用並且已知有效:以 "(引號字元)開頭的行會被 vi 忽略。
  3. 經典的 vi 對 map 和 map! 命令非常挑剔。從各個方面來說都應該起作用的定義可能會觸發奇怪的錯誤訊息。這是由於經典的 vi 對此類定義的解析器和直譯器有限。將 map 或 map1 命令拆分為幾個較小的命令有時可以幫助解決問題。

許多克隆透過允許 .exrc 檔案中的空行,以及透過正式指定 " 作為註釋字元,放鬆了這些規則。此外,好的克隆應該不會遇到 map 或 map! 規範的問題。

"
" This is a comment in an .exrc file
" A .exrc file must not contain empty lines, so
" comment lines need to be used to separate entries
"
set sm
set sw=8
"
set wm=8
"
" map 'g' to go to begin of file
map g 1G
" rcs check-out (/co) and check-in (/ci)
map /co :w! %.co.bak^M:!co -l %^M:e!
map /ci :w^M:!ci -u %^M:e!^M
"
" Abbreviations
ab Lx Linux

標籤

[edit | edit source]

概述

[edit | edit source]

vi 可以使用所謂的標籤檔案(或標籤)來允許快速導航(跳轉)到一組檔案中的“有趣”資訊。最常見的用法是在原始碼檔案中進行導航。例如,從某個函式的使用跳轉到該函式的定義,可能在另一個檔案中。

該機制相對簡單。您告訴 vi 跳轉到特定標籤。vi 會查詢包含該標籤的檔案,開啟該檔案並跳轉到該檔案中標籤的位置。為了查詢檔案和標籤的位置,vi 會查閱一個 *標籤檔案*。*標籤檔案* 包含標籤索引。標籤是可以在標籤檔案中找到索引條目的專案(例如某些程式語言物件)。當 vi 被要求跳轉到特定標籤時,vi 會查詢該標籤的索引條目,並使用該資訊跳轉到特定專案。

為了使用此功能,首先必須建立一個標籤檔案或一組標籤檔案,其中包含所有潛在有趣專案的條目。然後需要將這些標籤檔案或檔案告知 vi - 如果不使用預設檔名。例如,這可以透過在.exrc檔案中包含適當的命令來完成。

現代 IDE 提供類似的導航功能,但無需單獨構建標籤檔案。IDE 會即時構建必要的索引或使用快速的暴力全文字搜尋演算法。對於 vi 來說,建立標籤檔案的額外步驟在現代標準中是令人厭煩的。不過,vi 的標籤檔案系統仍然可以工作,並且可以使用。

標籤檔案格式、建立和 ctags(1)

[edit | edit source]

建立標籤檔案通常需要使用一個工具來分析輸入文字檔案(例如程式設計原始碼)併為在輸入文字檔案中找到的每個感興趣的專案生成條目。最常用的工具稱為 ctags(1),它是標準的 Unix 程式。幾個 vi 克隆自帶了 ctags 的版本,有時稱為不同的名稱。

ctags 瞭解多種程式語言的語法,併為函式名、宏定義等專案生成索引資訊。

如果 ctags 不可用,或者 ctags 的可用版本不支援使用的程式語言,也可以使用 awk(1)、sed(1) 或 perl(n) 等文字處理工具和一些巧妙的指令碼生成標籤檔案,因為標籤檔案是 ASCII 檔案。

標籤檔案中的條目通常如下所示

 tag-name<TAB>file-name<TAB>ex-command
tag-name
專案的名稱。例如函式名或宏名。
file-name
包含 *tag-name* 專案的檔案的名稱
ex-command
一個 ex 編輯器命令,指示如何在檔案中定位該專案。這可以是任何 ex 命令。但兩種型別的 ex 命令最合理
  1. 在簡單的形式中,*ex-command* 是一個行號,這實際上是一個有效的 ex 命令。
  2. 但是,通常最好使用搜索模式,例如/tag-name/這提供了一些靈活性,如果檔案稍後被編輯。它減少了必須重建標籤檔案的次數,因為某些東西在檔案內部移動了。ctags 也主要生成模式搜尋命令,而不是行號。

通常,vi 克隆允許對這種格式進行一些擴充套件。檢視特定的文件。

標籤檔案應按字母順序排序以加快操作速度。如果無法做到這一點,可以使用 vi 的 -S 命令列選項。

通常不建議透過手動執行 ctags 或自己的工具來生成標籤檔案。相反,標籤檔案的構建通常更好地整合到軟體構建系統中。對於 Unix 來說,這意味著使用 *Makefiles*。通常,用於生成標籤檔案的 make(1s) 目標稱為 *tags*,因為這是要建立的標籤檔案的名稱

# Makefile snippet
SRCS = ... # all source code
tags: $(SRCS)
        ctags -dt $(SRCS)

Ex 命令

[edit | edit source]

預設情況下,vi 在名為tags的檔案中查詢所有標籤。可以使用以下 ex 命令更改此檔名。事實上,可以指定多個檔名。它們都載入以查詢標籤。該命令最好放在特定於專案的.exrc檔案中包含適當的命令來完成。

:set tags=filename[\ filename ...]<CR>
設定包含標籤資訊的 filename 的名稱。如果要提供多個標籤 *filename*,該命令的語法在不同的 vi 版本之間略有不同。檔名必須用“\ ”(反斜槓空格)或“;”(分號)分隔。

可以透過以下 ex 命令導航到標籤。還有一個 vi 命令可以執行此操作。

:ta tag-name<CR>
或者
:tag tag-name<CR>
在標籤檔案(s)中查詢 *tag-name*,開啟索引條目中命名的檔案並執行索引條目中的 *ex-command*。這將有效地將使用者定位到定義符號 *tag-name* 的檔案和位置。該命令還會記住標籤堆疊上的當前檔案和位置。


vi 中的 EX 命令

[edit | edit source]

Ex 是一個行編輯器,是螢幕編輯器 vi 的基礎。Ex 命令對當前行或檔案中的一系列行起作用。

Ex 命令的語法
:[address] command [options]

“:” 指定一個 Ex 命令。

地址
“地址”指定作為命令物件的行號或行範圍。如果沒有給出地址,則當前行是命令的物件。

地址範圍可以透過以下任一方式在 Ex 命令語法中指定。

語法 範圍
 :% 檔案中的所有行。
:1,$ 檔案中的所有行。
:^,$ 檔案中的所有行。
:X,Y 從行號 X 到行號 Y 之間的所有行。
:.,.+n 從當前行到下一行 n 行的所有行。
:.,.-n 從當前行到上一行 n 行的所有行。
:X;Y 從行號 X 到行號 Y,將當前行設定為行號 X。
:X,+n 從行號 X 到當前行後的下一行 n 行的所有行。
:X,-n 從行號 X 到當前行前的上一行 n 行的所有行。
:X 行號 X。
:. 當前行。
:$ 檔案的最後一行。
:0 檔案的首行。
:X-n 在行號 X 之前 n 行的行。
:X+n 在行號 X 之後 n 行的行。
:'b 用字母 b 標記的行。
:' 標記的行。
:/word 包含模式 word 的下一行。
:?word 包含模式 word 的上一行。


命令

命令 Ex 語法 操作
替換 :%s/str1/str2/g 將整個檔案中指定的地址範圍內的 str1 替換為 str2。
複製和貼上 :t8 複製當前行並在行號 8 後貼上。
複製和貼上 :9t11 複製第 9 行並在行號 11 後貼上。
複製和貼上 :5,8t10 複製第 5 行到第 8 行並在行號 5 後貼上。
複製和貼上 :10,14co20 複製第 10 行到第 14 行並在行號 20 後貼上。
移動和貼上 :m8 剪切當前行並在行號 8 後貼上。
移動和貼上 :9m11 剪下第 9 行並在行號 11 後貼上。
移動和貼上 :5,8m10 剪下第 5 行到第 8 行並在行號 5 後貼上。
將/複製到命名緩衝區中。 :3,10y p 將第 3 行到第 10 行之間的文字複製到緩衝區 p(單個小寫字元)中。
將/複製。 :3,10y 將第 3 行到第 10 行之間的文字複製到臨時緩衝區中。
貼上/放置 :10p 將臨時緩衝區中的文字貼上到第 10 行。
貼上/放置 :p 將臨時緩衝區中的文字貼上到當前行。
貼上/放置 :+10p 將臨時緩衝區中的文字貼上到當前行後的第 10 行。
寫入/儲存檔案 :w! 儲存當前檔案。
寫入/儲存檔案 :w fname 將當前檔案儲存為 fname。類似於 Windows 作業系統中的“另存為”。
寫入/儲存檔案 :15,30w fnew 將當前檔案中的第 15 行到第 30 行儲存到名為 fnew 的新檔案中。
寫入/儲存檔案 :15,30w >> fexist 將當前檔案中的第 15 行到第 30 行追加到名為 fexist 的檔案中。
寫入/儲存檔案 :x! 強制儲存並退出當前檔案。
退出檔案 :q 退出當前檔案。
退出檔案 :q! 強制退出當前檔案,不儲存。
編輯/重新整理 :e! 重新整理 - 丟棄未儲存的更改。
編輯 :e fname 編輯名為 fname 的檔案,而不退出 vi。
編輯 :n 編輯下一個檔案,而不退出 vi。
編輯 :p 編輯上一個檔案,而不退出 vi。
編輯 :rew 編輯上一個檔案,而不退出 vi。
插入檔案 :r fname 在當前游標位置插入名為“fname”的檔案中的所有文字。
讀取/插入 :r! command 在當前游標位置插入命令的輸出。
讀取/插入 10:r! command 在第 10 行插入命令的輸出。
插入檔案 :r fname 在當前游標位置插入名為“fname”的檔案中的所有文字。
插入文字 :45i! 在第 45 行設定插入模式。
追加文字 :45a! 在第 45 行設定追加模式。
刪除行 :d 刪除當前行。
刪除行 :45d 刪除第 45 行。
刪除行 :.,.+15d 刪除當前行和接下來的 15 行之間的所有行。
刪除行並放入緩衝區 :.,.+15d f 刪除當前行和接下來的 15 行之間的所有行,並將它們放入名為 f 的緩衝區。
標記一行 :10ma f 用單個小寫字母 f 標記第 10 行。稍後使用 'f 返回標記位置。
Shell 命令 10,15:! command 在 shell 中執行命令。將第 10 行和第 15 行之間的文字作為命令的標準輸入,並用輸出替換這些行。
檢視 :10z 設定檢視,將第 10 行放在螢幕頂部。
檢視 :10z+ 設定檢視,將第 10 行放在螢幕頂部。
檢視 :10z- 設定檢視,將第 10 行放在螢幕底部。
檢視 :100z. 設定檢視,將第 100 行放在螢幕中央。
檢視 :100z^ 設定檢視,將第 100 行放在螢幕中央,並將當前行設定為第 100 行。
檢視 :10z+ 5 設定檢視,將第 10 行放在螢幕頂部,並顯示第 10 行之後的 5 行。
狀態 :f 在螢幕底部顯示當前位置和檔名。它還指定自檔案開啟以來是否對檔案進行了任何更改。


選項

選項 操作
! 指定命令必須強制執行。
目標 指定貼上文字的行號。與複製和移動命令一起使用。
計數 指定命令重複的次數。該數字始終在命令之後。
fname 指定物件是一個名為“fname”的檔案。

Vi 命令

[edit | edit source]

可以使用以下 vi 命令導航到標籤

^]
取游標位置處的 tag-name,在標籤檔案(多個)中查詢它並導航到它,類似於:taex 命令。該命令還會記住標籤棧上的當前檔案和位置。

以下命令使用標籤棧返回到之前的位置。舊版本的 vi 未實現它

^T
從標籤棧中獲取之前的位置和檔案並返回。資料將從檔案中刪除。

命令列

[edit | edit source]

也可以使用標籤名而不是檔名啟動 vi。請參閱 -t 命令列選項。

Shell 轉義

[edit | edit source]

在 vi 中工作時,可能需要執行另一個作業系統命令。在如今,這不是什麼大問題。可以開啟另一個終端視窗並隨意操作。但是,在使用 vi 時,這並非必要。vi 與許多舊的互動式 Unix 工具一樣,包含在編輯器中執行作業系統命令或啟動命令列直譯器(shell)的功能。這可以追溯到沒有圖形使用者介面,並且像 vi 這樣的編輯器會佔用終端的整個螢幕(當然是指真正的終端,而不是終端模擬器)的時代。能夠從 vi 中執行命令可以省去先退出編輯器才能檢視某些內容的麻煩,例如,檢視手冊頁。

此外,vi 還提供將其他命令的文字輸出直接插入正在編輯的文字中的功能。

Ex 命令

[edit | edit source]

實際上,在 vi 中執行另一個命令的編輯器命令是作為 ex 命令實現的。也就是說,它們以命令模式下的熟悉“:”開頭。

要從 vi 中執行一個命令,可以鍵入

:!command<CR>
<CR>

command 結束時,必須按回車鍵(上面顯示的第二個 <CR>)才能返回 vi。然後 vi 重新繪製螢幕並繼續從停止的地方進行編輯。

要重複最後一個 command,只需鍵入

:!!<CR>
 <CR>

可以使用:!!將內容追加到之前的命令,後面加上要追加的內容。例如,以下兩個命令中的第二個

:!ls<CR>
 <CR>
 :!! | more<CR>
 <CR>

實際上等同於

:!ls | more<CR>
 <CR>

(注意,ls 是 Unix 命令,用於列出目錄,more 是 Unix 命令,用於分頁輸出,因此它不會簡單地從螢幕上滾動)。

一旦將某些內容追加到命令,它就會成為最後一個記住的命令的一部分。因此,在上面的示例中,另一個

:!!<CR>
 <CR>

將等同於

:!ls | more<CR>
 <CR>

而不是

:!ls<CR>
 <CR>

可以在 shell 轉義中使用兩個佔位符來表示當前檔名或之前編輯的檔名

%
是當前檔名的佔位符,
#
是之前編輯的檔名的佔位符。

例如,如果正在編輯一些 shell 指令碼並想嘗試執行它,可以鍵入以下命令來儲存檔案(:w),將檔案屬性設定為可執行(!chmod ...),並執行它(!%):

:w<CR>
 :!chmod 755 %<CR>
 <CR>
 :!%<CR>
 <CR>

如果檔名例如是 script.sh,則上述操作相當於鍵入

:w<CR>
 :!chmod 755 script.sh<CR>
 <CR>
 :!script.sh<CR>
 <CR>


除了從 vi 中執行命令之外,還可以從 vi 中啟動 shell。vi 有一個自己的命令用於執行此操作,該命令會查詢使用者的預設 shell(例如,Bourne shell 或 C shell)並啟動它。請務必注意,將啟動一個新的 shell。使用者不會返回到啟動 vi 的 shell。該命令稱為 :sh,它可以按如下方式使用

<ESC>:sh<CR>
$ #shell commands, when done exit shells:
$ exit<CR>

Vi 命令

[edit | edit source]

可以將當前正在編輯的文字的全部或部分內容透過外部程式過濾。然後用外部命令的輸出替換原始文字。

此功能的經典示例是使用 Unix 文字格式化程式 fmt。vi 本身沒有任何特定的格式化功能,但是,透過從 vi 中執行文字或部分文字,使用外部格式化程式,可以輕鬆實現所需的格式化。

用於過濾文字的 vi 命令是!(注意,與 ex shell 轉義命令不同,沒有前導的:). !遵循通常的 vi 命令格式。因此可以指定它應該適用的範圍。例如!!表示過濾當前行,或者!}表示過濾當前段落。

!vi 命令後面必須跟用於過濾的外部程式的名稱。例如,要使用前面提到的 Unix 文字格式化程式 fmt 格式化當前段落,可以鍵入

!}fmt<CR>

!也可以用於將某些外部命令的輸出插入到當前編輯的文字中。為此,首先建立一個新的空行(例如,使用o),然後使用!!用命令的輸出替換空行。例如,

o<ESC>!!ls<CR>

將在 Unix 中將當前目錄中的檔案列表包含到文字中。

從緩衝區執行命令

[edit | edit source]

此模組是一個 存根。您可以透過 修復它 來幫助 Wikibooks。

@b
執行儲存在緩衝區 b 中的命令。

面向程式設計師的 vi

[edit | edit source]

經典的 vi 提供了許多對程式設計師有用的功能。vi 是由程式設計師為程式設計師製作的——但在程式設計方式不同的時代。根據今天的標準,經典 vi 的程式設計支援不太好,但當然仍然可以使用。而且,使用 vi 編輯程式設計程式碼仍然比使用任何 ...pad 編輯器(如 notepad(Windows)或 dtpad(CDE/Motif))更方便。vi 可能在 Unix 系統上效果最佳,因為 Unix 附帶了許多文字過濾器,並且可以輕鬆地用指令碼編寫額外的專用過濾器。

vi 中對程式設計師有用的功能有

自動縮排和手動行移位

[edit | edit source]

請參閱 縮排和移位

模型行

[edit | edit source]

模型行用於設定每種語言的預設值——如果安全性不是問題(請參閱 模型行

用於導航的標籤

[編輯 | 編輯原始碼]

參見 標籤

Shell 轉義

[編輯 | 編輯原始碼]

參見 Shell 轉義

  • 使用 Shell 轉義的一種方法是在 vi 中執行 makefile 或編譯器。一般來說,在嘗試編譯檔案之前先儲存當前檔案是一個好主意。
<ESC>:w<CR>
:!make<CR>
or <ESC>:w<CR> :!cc %<CR>
and afterwards <ESC>:w<CR> :!!<CR>
  • 另一種方法是透過外部命令過濾原始碼,例如透過特定語言的註釋格式化程式。例如,以下命令將透過名為 recomment 的外部註釋格式化程式過濾當前段落(不是標準的 Unix 程式,但可以作為單獨的指令碼使用)。
!}recomment
參見 [1] 獲取適用於 Unix 的 recomment 指令碼。

編輯多個檔案

[編輯 | 編輯原始碼]

vi 可以使用檔案列表啟動。

vi file1 file2 file3 ...

結合其他 Unix 功能,如檔案匹配,這可能是一個強大的功能。例如,要開啟目錄中的所有 C 原始碼,包括標頭檔案(.h),可以使用以下命令

vi *.[ch]

或者,要查詢包含特定關鍵字的所有檔案並開啟它們,可以使用類似的命令

vi `grep -l Keyword *.txt`

使用檔案列表啟動 vi 後,可以使用以下命令在列表中導航。

:n
next - 移動到檔案列表中的下一個檔案。
:rew
rewind - 倒回檔案列表,並開啟列表中的第一個檔案。

像 vim 這樣的 vi 克隆通常提供更多命令,例如在檔案列表中後退一個檔案。

在兩個檔案之間切換

[編輯 | 編輯原始碼]
  • 使用#作為最後一個檔案的名稱,在兩個檔案之間切換。例如,在 C 原始檔和相應的標頭檔案之間切換。
:e x.c<CR>
:e x.h<CR>
some changes to x.h, then going back to x.c
<ESC>:w<CR>
:e#<CR>
  • 使用以下命令在兩個檔案之間切換CTRL-^。這是被遺忘的 vi 命令之一。

error(1) 程式

[編輯 | 編輯原始碼]

Unix 上的 error(1) 程式可用於捕獲來自編譯器的錯誤訊息,並在編輯器中從一條錯誤訊息跳轉到另一條錯誤訊息。error 的工作方式過時了。它會解析來自編譯器的錯誤訊息,並將它們作為註釋插入編譯器檢測到錯誤的原始檔中。由於 error 使用###%%%在原始檔中標記錯誤訊息,因此可以使用 vi 命令(如/n.

進行導航。

  1. 使用 error 與 vi 有兩種常見的方法。-v從 vi 外部,讓 error 啟動 vi。error 可以使用
$ cc *.c 2>&1 | error -v
# Notes:
#  cc    - the C compiler
#  *.c   - all C files in the current directory
#  2>&1  - Standard error output is redirected to normal standard output
#  |     - the output is feed to error as input
標記在所有在編譯期間產生錯誤的檔案上啟動 vi。:e!2. 從 vi 內部,在當前檔案上。首先儲存檔案,然後嘗試編譯它,使用 error 處理潛在的錯誤訊息,然後重新讀取可能更改的原始檔(/###:
first time
<ESC>:w<CR>
:!cc % 2>&1 | error<CR>
:e!<CR>
/###<CR>
and afterwards <ESC>:w<CR> :!!<CR> :e!<CR> /###<CR>
),最後使用
搜尋第一個標記。

注意

error 是一種糟糕的解決方案,它會嚴重破壞原始碼和版本控制系統!我們建議您至少嘗試一次,並形成自己的看法。此外,請先檢視 error 的手冊頁。像 vim 這樣的 vi 克隆提供了一個更加合理系統。在這裡,編輯器會執行編譯器(或 make(1s)),並捕獲編譯器的輸出。vim 會將資訊記錄在錯誤訊息檔案中。然後,vim 透過從錯誤訊息中提取檔名和行號並跳轉到這些位置來允許導航原始碼。這與 IDE 提供的機制相同。

宏和快捷方式[編輯 | 編輯原始碼]vi 提供:map:map!命令來定義有用的快捷方式和宏,以及

ab
qqI//<Esc>jq
places a comment at the beginning of a line and moves down
來提供縮寫。

待辦:提供一些此類宏?

這是(上面)您所說的宏嗎?

概述

nroff/troff 排版支援

[編輯 | 編輯原始碼]

[編輯 | 編輯原始碼]

vi 支援編輯適用於 Unix 排版程式 nrofftroff 的文字檔案。如今,這些排版程式最“常見”的用途可能是編寫 Unix 應用程式的手冊頁(man)。

.SH "A SECTION HEADER"
Some text making up the first paragraph in the section.
More text in the paragraph.
.PP
A new paragraph has been started.
More text in this second paragraph.
.PP
Yet another paragraph.
.\"
.\" A comment infront of the next section header
.\"
.SH "SECTION HEADER 2"
Paragraph text.

編寫 nroff/troff 輸入文字檔案的功能始終處於啟用狀態,沒有需要開啟的特殊 vi 模式或選項。由此可以推斷出,vi 中並沒有太多特定於 nroff/troff 的操作。實際上,vi 只提供簡單的導航方式來在 nroff/troff 段落和節之間移動。然而,這些功能在編輯 nroff/troff 檔案時有所幫助。nroff/troff 的文字檔案格式很簡單。普通文字和宏混合在一起,其中宏指示文字的格式。宏以第一列中的“.”開頭,後面跟著一到兩個字母的宏名稱,以及可選的宏引數。包含一些宏的典型 nroff/troff 文字檔案可能如下所示為了簡化此類文字檔案的導航,vi 瞭解節(上面示例中的.SH) 和段落(示例中的

.PP

<ESC>:w<CR>
:!nroff -man % | more<CR>

選項

) 的常見宏名稱,並提供命令來移動到下一個/上一個節。宏名稱列表在 vi 中是可配置的。

許多常見的 vi 功能在編輯 nroff/troff 文字時也有幫助。例如,使用 Shell 轉義從 vi 中執行排版程式。以下命令將使用手冊頁宏格式化當前檔案[編輯 | 編輯原始碼]以下選項用於定義 vi 識別的 nroff/troff 宏名稱。與所有選項一樣,可以使用

:set option[=value]
:set
ex 命令更改它們。nroff/troff 的文字檔案格式很簡單。普通文字和宏混合在一起,其中宏指示文字的格式。宏以第一列中的“.”開頭,後面跟著一到兩個字母的宏名稱,以及可選的宏引數。包含一些宏的典型 nroff/troff 文字檔案可能如下所示, sections, vi 解釋為節分隔符的宏名稱列表。列表中的兩個連續字元構成一個宏名稱。通常,vi 的預設設定包含,以及.NH.H
sections=SHNHH HU
.HU
或者
。因此,sections 選項的讀取方式為
paragraphspara, vi 解釋為段落分隔符的宏名稱列表。列表中的兩個連續字元構成一個宏名稱。vi 的預設設定通常包含, .SH, .IP, .LP, .QP, .PL.Ib
paragraphs=IPLPPPQPPLIbp

Vi 命令

.p

。因此,paragraphs 選項的讀取方式為

[[
[編輯 | 編輯原始碼]
]]
在命令模式下,以下命令與處理 nroff/troff 文字相關。
{
移動到上一個節。
}
移動到下一個節。

移動到上一個段落。

(
移動到下一個段落。
)
為了完整起見,


學習 vi 編輯器: 熟悉基本任務使工作更輕鬆高階任務詳細資訊Vi 克隆 (Vim基本導航模式技巧和竅門程式設計師需要了解的有用內容增強 VimVim 在 Windows 上VimL 指令碼語言, Vile, BB vi)vi 參考

移動到上一個句子。
華夏公益教科書