Vimの問題は、viを理解しないことです。
あなたは切断について言及しyy
、行全体を切断することはほとんどありませんと不平を言います。実際、ソースコードを編集するプログラマーは、行全体、行の範囲、およびコードのブロックで作業することを望むことがよくあります。ただし、yy
テキストを匿名コピーバッファーにヤンクする(またはviで呼び出される「登録」)ための多くの方法の1つにすぎません。
viの「禅」とは、言語を話しているということです。イニシャルy
は動詞です。ステートメントyy
はの同義語ですy_
。y
それは、このような一般的な操作であることから、それが簡単に入力できるようにすることまで倍増しています。
これは、dd
P
(現在の行を削除してコピーを所定の場所に貼り付け、副作用としてコピーを匿名レジスタに残す)としても表現できます。y
そしてd
「動詞」自分として任意の動きを取る「対象。」したがってyW
、「ここ(カーソル)から現在/次の(大きな)単語の終わりまでy'a
ヤンク」であり、「ここから、 ' a ' という名前のマークを含む行までヤンクします。」
基本的な上、下、左、右のカーソルの動きだけを理解している場合、viは「ノートパッド」のコピーよりも生産性が高くありません。(それでも、構文の強調表示と、約45KB程度の大きなファイルを処理する機能はありますが、ここで私と一緒に作業してください)。
viには26の「マーク」と26の「レジスタ」があります。m
コマンドを使用して、任意のカーソル位置にマークが設定されます。各マークは、1つの小文字で指定されます。したがってma
、 ' a 'マークを現在の場所にmz
設定し、 ' z 'マークを設定します。'
(一重引用符)コマンドを使用して、マークを含む行に移動できます。したがって'a
、 ' a 'マークを含む行の先頭に移動します。`
(逆引用符)コマンドを使用して、マークの正確な位置に移動できます。したがって`z
、 ' z 'マークの正確な位置に直接移動します。
これらは「動き」なので、他の「ステートメント」の主題としても使用できます。
したがって、テキストの任意の選択を切り取る1つの方法は、マークをドロップすることです(通常、「a」を「最初の」マークとして、「z」を次のマークとして、「b」を別のマークとして、「e」をさらにもう1つ(viを使用してから15年間で、4つ以上のマークをインタラクティブに使用したことを覚えていない。マークとレジスターがマクロによってどのように使用されるかについて、独自の規則を作成し、インタラクティブなコンテキストを妨げないようにする)。次に、目的のテキストの反対側に移動します。どちらから始めてもかまいません。その後、単純d`a
にカットまたはy`a
コピーに使用できます。したがって、プロセス全体で5つのキーストロークのオーバーヘッドがあります(「挿入」で開始した場合は6つ) 」モードとする必要がEscコマンドモードを出力します)。切り取りまたはコピーしたら、コピーの貼り付けは1回のキーストロークですp
。
これはテキストをカットまたはコピーするための1つの方法であると私は言います。しかし、それは多くの1つにすぎません。多くの場合、カーソルを移動してマークをドロップしなくても、テキストの範囲をより簡潔に説明できます。たとえば、私が使用することができ、テキストの段落にいる場合{
や}
、それぞれの段落の最初か最後まで動き。したがって、テキストの段落を移動するには、{
d}
(3つのキーストローク)を使用してテキストを切り取ります。(私がすでに段落の最初または最後の行にいる場合は、単にd}
またはをd{
それぞれ使用できます。
「段落」の概念は、通常は直感的に合理的なものにデフォルト設定されます。したがって、散文だけでなくコードでも機能します。
関心のあるテキストの一方の端またはもう一方の端をマークするパターン(正規表現)をよく知っています。前方または後方の検索は、viの動きです。したがって、これらは「ステートメント」の「サブジェクト」としても使用できます。したがってd/foo
、現在の行から文字列「foo」を含む次の行に切り取り、現在の行からy?bar
「bar」を含む最新の(前の)行にコピーするために使用できます。行全体が不要な場合でも、検索動作を(独自のステートメントとして)使用し、マークをドロップして`x
、前述のコマンドを使用できます。
「動詞」と「主語」に加えて、viは「オブジェクト」も持っています(文法的には)。これまでは、匿名レジスタの使用についてのみ説明してきました。ただし、「オブジェクト」参照の前に(二重引用符修飾子)を付けることにより、26個の「名前付き」レジスタのいずれかを使用できます"
。したがって、使用する場合"add
、現在の行を ' a 'レジスタにカットし、使用する場合"by/foo
、ここから「foo」を含む次の行のテキストのコピーを ' b 'レジスタにヤンクします。レジスタから貼り付けるには、貼り付けの前に同じ修飾子シーケンスを付けるだけです:"ap
' a 'レジスタのコピーを貼り付けます"bP
' b 'から現在の行の前までのコピーを貼り付けます。
この「接頭辞」の概念は、文法上の「形容詞」と「副詞」の類似物をテキスト操作の「言語」に追加します。ほとんどのコマンド(動詞)と動き(動詞またはオブジェクト、コンテキストによって異なります)も数値の接頭辞を取ることができます。3J
「次の3行を結合する」をd5}
意味し、「現在の行から5番目の段落の終わりまでここから削除する」を意味します。
これはすべて中間レベルのviです。それはVim固有のものではなく、習得する準備ができていれば、viにははるかに高度なトリックがあります。これらの中間概念のみを習得した場合、テキスト操作言語は十分に簡潔で表現力があり、エディターの「ネイティブ」言語を使用してほとんどのことを簡単に実行できるため、マクロを記述する必要はほとんどありません。
より高度なトリックのサンプル:
多数の:
コマンドがあり、特に:% s/foo/bar/g
グローバル置換テクニックがあります。(それは高度ではありませんが、他の:
コマンドは可能です)。:
コマンドの全セットは、歴史的にed(ラインエディタ)および後にex(拡張ラインエディタ)ユーティリティとしてviの以前の化身に継承されました。実際、viはexへのビジュアルインターフェースであるため、このように呼ばれています。
:
コマンドは通常、テキスト行に対して機能します。 edとexは、端末画面が一般的ではなく、多くの端末が「テレタイプ」(TTY)デバイスであった時代に書かれました。したがって、非常に簡潔なインターフェースを介してコマンドを使用して、テキストの印刷されたコピーから作業するのが一般的でした(一般的な接続速度は110ボー、またはおよそ11秒あたり11文字で、これは高速タイピストよりも遅く、遅延は一般的でした)マルチユーザーのインタラクティブセッション。さらに、紙を節約する動機がしばしばありました)。
そのため、ほとんどの:
コマンドの構文には、アドレスまたはアドレス範囲(行番号)とそれに続くコマンドが含まれています。当然一方がリテラル行番号を使用することができます。:127,215 s/foo/bar
また、などのいくつかの略語を使用することができる一方127との間及び215の各ライン上の「BAR」に「FOO」の最初の発生を変更する.
か、$
それぞれ現在の行と最後の行のため。また、相対接頭辞+
を使用して-
、現在の行の後または前のオフセットをそれぞれ参照することもできます。したがって:.,$j
、「現在の行から最後の行まで、すべてを1つの行に結合する」という意味です。 (すべての行):%
と同義:1,$
です。
:... g
そして:... v
コマンドは、彼らが信じられないほど強力であるとして、いくつかの説明を負担します。 :... g
パターン(正規表現)に一致するすべての行に後続のコマンドを「グローバルに」適用する接頭辞ですが:... v
、指定されたパターン(「conVerse」の「v」)に一致しないすべての行にそのようなコマンドを適用します。他のexコマンドと同様に、これらはアドレス指定/範囲参照によってプレフィックスを付けることができます。したがって:.,+21g/foo/d
、「現在の行から次の21行までの文字列 "foo"を含む行をすべて削除:.,$v/bar/d
する」、「ここからファイルの終わりまで、文字列 "bar"を含まない行を削除する」を意味します。
興味深いのは、一般的なUnixコマンドのgrepが実際にこのexコマンドから発想を得た(そして、ドキュメント化された方法にちなんで名前が付けられている)ことです。元のコマンド:g/re/p
(grepが)彼らは「グローバル」「正規表現」(再)「を含む行を」印刷する方法を文書化の方法でした。ときEDとEXを使用して、:p
コマンドは、誰もが学習し、任意のファイルを編集する際に、多くの場合、最初の1が使用した最初の一つでした。現在のコンテンツを印刷する方法でした(通常、一度に1ページだけを使用:.,+25p
するなど)。
なお、:% g/.../d
または(その逆/ CONVERSEの対応::% v/.../d
最も一般的な使用パターンであるしかし他のいくつかあります。ex
価値が覚えているコマンド:
を使用m
して、線を移動したり、線j
を結合したりできます。たとえば、リストがあり、それらを削除せずに一致するものすべて(または逆に一部のパターンに一致しないもの)を分離する場合は、次のようなものを使用できます:% g/foo/m$
。...そしてすべての "foo"行は次の場所に移動されます。ファイルの終わり。(ファイルの最後をスクラッチスペースとして使用することに関する他のヒントに注意してください)。これにより、残りのリストから抽出されている間、すべての「foo」行の相対順序が保持されます。(これは次のようなことと同じです:(1G!GGmap!Ggrep foo<ENTER>1G:1,'a g/foo'/d
ファイルを独自の末尾にコピーし、末尾をでフィルタリングしてgrep
、ヘッドからすべてのものを削除します)。
行を結合するには、通常、前の行に結合する必要のあるすべての行のパターンを見つけることができます(たとえば、箇条書きリストで "^ *"ではなく "^"で始まるすべての行)。その場合、私は次のように使用します:% g/^ /-1j
(一致するすべての行について、1行上に移動してそれらを結合します)。(ところで、箇条書きの行を検索して次の行に結合しようとする箇条書きリストは、いくつかの理由で機能しません... 1つの行を別の行に結合することができ、すべての行にすべての行を結合することはできません。その継続、それはマッチでペアでのみ機能します)。
言うまでもないことですが、古いs
(フレンド)コマンドg
をv
(global / converse-global)コマンドで使用できます。通常、これを行う必要はありません。ただし、他のパターンに一致する行のみを置換したい場合を考えてください。多くの場合、キャプチャで複雑なパターンを使用し、後方参照を使用して、変更したくない行の部分を保持できます。ただし、多くの場合、一致を置換から分離する方が簡単です。:% g/foo/s/bar/zzz/g
「foo」を含むすべての行で、すべての「bar」を「zzz」に置き換えます。(何かのようなもの:% s/\(.*foo.*\)bar\(.*\)/\1zzz\2/g
同じ行で "foo"によってPRECEDEDされた "bar"のインスタンスの場合にのみ機能します。それはすでに十分に手に負えず、 "bar"が "foo"に先行するすべてのケースをキャッチするためにさらにマングルする必要があります)
重要なのは、コマンドセットには、、、および行だけp
でs
はありません。d
ex
:
アドレスはまた、マークを参照することができます。したがって、あなたは使用することができます。:'a,'bg/foo/j
その次の行に文字列fooのを含む任意の行を結合するために、それは「の間の線の間にある場合」と「B」マーク。(はい、前述のコマンド例はすべて、このような種類のアドレス指定式をプレフィックスとして付けることにより、ファイルの行のサブセットに制限できます)。ex
これはかなりあいまいです(このようなものを過去15年間で数回しか使用していません)。しかし、私は時間をかけて正しい呪文を考えていればおそらくもっと効率的にできたであろうことを反復的かつ対話的にしばしば行ってきたことを自由に認めます。
別の非常に便利なviまたはexコマンドは:r
、別のファイルの内容を読み込むことです。したがって:r foo
、現在の行に「foo」という名前のファイルの内容を挿入します。
より強力なのは:r!
コマンドです。コマンドの結果を読み取ります。これは、viセッションを一時停止し、コマンドを実行し、その出力を一時ファイルにリダイレクトし、viセッションを再開し、tempからコンテンツを読み込むのと同じです。ファイル。
さらに強力なのは(bang)コマンド!
と:... !
(ex bang)コマンドです。これらは外部コマンドを実行し、結果を現在のテキストに読み込みます。ただし、コマンドを使用して、選択したテキストをフィルター処理します。これにより、ファイル内のすべての行を並べ替えることができます1G!Gsort
(これG
はviの「goto」コマンドです。デフォルトではファイルの最後の行に移動しますが、先頭に1などの行番号を付けることができます)。これはexバリアントと同等:1,$!sort
です。ライター!
は、Unixのfmtまたはfoldユーティリティを使用して、テキストの選択を再構成または「ワードラップ」します。非常に一般的なマクロは{!}fmt
(現在の段落を再フォーマットします)。プログラマーは、インデントやその他のコード再フォーマットツールを使用して、コードを実行したり、コードの一部だけを実行したりすることがあります。
:r!
および!
コマンドを使用すると、外部ユーティリティまたはフィルターをエディターの拡張機能として扱うことができます。データベースからデータをプルするスクリプト、またはWebサイトからデータをプルするwgetまたはlynxコマンド、またはリモートシステムからデータをプルするsshコマンドでこれらを時々使用しました。
別の便利なexコマンドは:so
(の略:source
)です。これは、ファイルの内容を一連のコマンドとして読み取ります。viを通常の方法で開始すると、暗黙的に:source
オン~/.exinitrc
ファイルが実行されます(そして、Vimは通常これを~/.vimrc
で実行しますが、当然のことながら十分です)。これを使用すると、新しいマクロ、略語、およびエディター設定のセットを単に調達することで、その場でエディタープロファイルを変更できます。卑劣な場合は、これをオンデマンドでファイルに適用するex編集コマンドのシーケンスを格納するためのトリックとして使用することもできます。
たとえば、wcを介してファイルを実行する7行のファイル(36文字)があり、そのワードカウントデータを含むファイルの上部にCスタイルのコメントを挿入します。次のようなコマンドを使用して、その「マクロ」をファイルに適用できます。vim +'so mymacro.ex' ./mytarget
(通常+
、viおよびVimのコマンドラインオプションは、特定の行番号で編集セッションを開始するために使用されます。ただし、「ソース」コマンドなどの+
有効なexコマンド/式をここでは、簡単な例として、次のようなスクリプトをvi +'/foo/d|wq!' ~/.ssh/known_hosts
実行しています:サーバーのセットを再イメージングしているときに、SSHの既知のホストファイルからエントリを非対話的に削除します)。
通常、Perl、AWK、sed(実際には、edコマンドに触発されたgrepユーティリティのようなもの)を使用して、このような「マクロ」を書く方がはるかに簡単です。
@
コマンドは、おそらく最もはっきりしないのviコマンド。高度なシステム管理コースを10年近く教えることもあるので、これを使ったことがある人はほとんどいません。 @
レジスタの内容をviまたはexコマンドであるかのように実行します。
例:私がよく使用するの:r!locate ...
は、システム上のファイルを見つけて、その名前をドキュメントに読み込むためです。そこから不要なヒットを削除し、関心のあるファイルへの完全なパスのみを残します。Tabパスの各コンポーネントを手間をかけずに(または、タブ補完のサポートのないマシンでスタックしている場合)そのviのコピーで)私はちょうど使用します:
0i:r
(現在の行を有効な:rコマンドにするには)、
"cdd
(「c」レジスタへの行を削除するため)および
@c
そのコマンドを実行します。
それはたったの10回のキーストロークです(そして、式"cdd
@c
は事実上私にとって指マクロなので、一般的な6文字の単語と同じくらい迅速に入力できます)。
地味な考え
私はviのパワーのほんの一部にすぎませんでした。ここで説明したことは、vimが命名された「改善」の一部でさえありません!ここで説明したことはすべて、20年または30年前のviの古いコピーで機能するはずです。
今まで以上にviのパワーを使った人がいます。