*usr_12.txt*	For Vim バージョン 9.0.  Last change: 2021 Apr 19

		     VIM USER MANUAL - by Bram Moolenaar

				  便利な小技


コマンドを組み合わせれば、ほとんど何でもこなすことができます。この章では、便利
なコマンドの組み合わせをいくつか紹介します。今までに紹介したコマンドを主に使い
ますが、まだ紹介していないコマンドも少し登場します。

|12.1|	単語を置換する
|12.2|	"Last, First" を "First Last" に変更する
|12.3|	リストをソートする
|12.4|	行を逆順に並べ替える
|12.5|	単語を数える
|12.6|	マニュアルを引く
|12.7|	空白を取り除く
|12.8|	単語が使われている場所を検索する

次章: |usr_20.txt|  コマンドラインを素早く入力する
前章: |usr_11.txt|  クラッシュからの復帰
目次: |usr_toc.txt|

==============================================================================
*12.1*	単語を置換する

置換コマンドを使うと、文章中に現れる単語を別の単語に置換することができます: >

	:%s/four/4/g

"%" はすべての行を処理するための範囲指定です。末尾の "g" は、行のすべての単語
を置換するための指定です。

上記のコマンドは正しく動作しません。例えば、"thirtyfour" という単語がファイル
に含まれていた場合、"thirty4" に置換されてしまいます。これを防ぐには、"\<" を
使って単語の先頭にヒットさせます: >

	:%s/\<four/4/g

これでもまだ、"fourteen" のような単語が間違って置換されてしまいます。"\>" を
使って単語の末尾にヒットさせましょう: >

	:%s/\<four\>/4/g

プログラムを書いているなら、コメントの中にある "four" だけを置換したい場合もあ
るでしょう。コメントの中かどうかを区別するのは難しいので、置換コマンドに "c"
フラグを指定して、確認しながら置換してください: >


	:%s/\<four\>/4/gc


複数のファイル内で置換する
--------------------------

複数のファイル内で置換したい場合を考えます。ファイルを1つずつ開いて、その都度
コマンドを入力することもできますが、操作の記録と再実行を使えば、はるかに素早く
置換できます。
拡張子が ".cpp" の C++ ファイルが入ったディレクトリがあるとします。"GetResp"
という関数を "GetAnswer" に置換してみましょう。

	vim *.cpp		Vim を起動して、すべての C++ ファイルを引数リ
				ストに加える。Vim が起動すると、最初のファイル
				が表示されます。
	qq			レジスタ "q" に記録を開始する。
	:%s/\<GetResp\>/GetAnswer/g
				最初のファイルで置換コマンドを実行する。
	:wnext			ファイルを保存し、次のファイルに移動する。
	q			記録を終了する。
	@q			レジスタ "q" を実行する。置換コマンドと
				":wnext" が再実行されます。エラーメッセージが
				表示されたりしないか確認してください。
	999@q			レジスタ "q" を繰り返し実行し、残りのファイル
				をすべて処理します。

最後のファイルを処理したとき、もうそれ以上ファイルがないので、":wnext" コマン
ドがエラーメッセージを表示します。それにより、実行が中断され、すべてが完了しま
す。

	Note:
	記録されたコマンドの実行中にエラーが発生すると、実行は中断されます。
	ですから、エラーが出ないように注意して操作を記録してください。

まだ問題が1つ残っています。もしも、"GetResp" を含んでいないファイルがあった場
合、置換コマンドがエラーを発生し、そこで処理が停止してしまいます。それを避ける
には、置換コマンドに "e" フラグを指定してください: >

	:%s/\<GetResp\>/GetAnswer/ge

"e" フラグは、パターンが見つからなくてもエラーを発生させないための指定です。

==============================================================================
*12.2*	"Last, First" を "First Last" に変更する

次のような形式で名前の一覧があるとします:

	Doe, John ~
	Smith, Peter ~

これを次のように変更したいとします:

	John Doe ~
	Peter Smith ~

これはたった1つのコマンドでできてしまいます: >

	:%s/\([^,]*\), \(.*\)/\2 \1/

1つずつ説明しましょう。これが置換コマンドであることはわかりますよね。"%" はす
べての行を示す範囲指定です。つまり、ファイルのすべての行で置換が実行されます。
置換コマンドには "/from/to/" という形式で引数を指定します。スラッシュ (/) は
"from" パターンと "to" 文字列の区切りです。"from" パターンは次のようになってい
ます:
							\([^,]*\), \(.*\) ~

	1つ目の \( \) で囲まれた部分は "Last" です	\(     \)
	    コンマ (,) 以外の文字が			  [^,]
	    何文字でもマッチする			      *
	", " という文字にそのままマッチ			         ,
	2つ目の \( \) で囲まれた部分は "First" です	           \(  \)
	    どんな文字でも				             .
	    何文字でもマッチする				      *

"to" の部分には "\2" と "\1" が指定されています。これは後方参照というものです。
"\( \)" で囲まれた部分にマッチしたテキストを参照しています。"\2" は2つ目の
"\( \)" で囲まれた部分にマッチしたテキスト ("First" name) を参照しています。
"\1" は1つ目の "\( \)" ("Last" name) を参照しています。
置換コマンドの "to" 部分には最大で 9 個の後方参照を指定できます。"\0" はパター
ンがマッチしたテキスト全体になります。置換コマンドには他にもいくつか特殊なアイ
テムがあります。|sub-replace-special| を参照してください。

==============================================================================
*12.3*	リストをソートする

Makefile ではよく、ファイルのリストが使われます。例:

	OBJS = \ ~
		version.o \ ~
		pch.o \ ~
		getopt.o \ ~
		util.o \ ~
		getopt1.o \ ~
		inp.o \ ~
		patch.o \ ~
		backup.o ~

このリストをソートするには、外部コマンドの sort を使ってテキストをフィルタリン
グします: >

	/^OBJS
	j
	:.,/^$/-1!sort

リストの先頭 (行頭が "OBJS" で始まる行) に移動してから、一行下に移動、その行か
ら次の空行までの範囲をフィルタに通しています。ビジュアルモードで範囲を選択して
から "!sort" を実行する方法でも構いません。その方が入力は簡単です。行がたくさ
んある場合は少し面倒かもしれませんが。
結果は、次のようになります:

	OBJS = \ ~
		backup.o ~
		getopt.o \ ~
		getopt1.o \ ~
		inp.o \ ~
		patch.o \ ~
		pch.o \ ~
		util.o \ ~
		version.o \ ~


各行の末尾に行結合のためのバックスラッシュ (\) が使われている点に注意して下さ
い。並べ替えたために、これが壊れてしまいました。"backup.o" はリストの最後にあっ
たので行末にバックスラッシュが付いていませんでしたが、並べ替えによって別の場所
に移動したため、バックスラッシュが必要になったのです。
一番簡単な解決方法は "A \<Esc>" でバックスラッシュを追加することです。最後の行
にあるバックスラッシュは次の行を空白行にしておけば削除しなくても問題ありませ
ん。これで同じ問題は二度と起きないでしょう。

==============================================================================
*12.4*	行を逆順に並べ替える

|:global| コマンドと |:move| コマンドを組み合せて、全ての行を 1 行目の上に移動
することで、行を逆順に並べ替えたファイルを作ることができます。コマンドは次の通
りです: >

	:global/^/move 0

短縮して書くこともできます: >

	:g/^/m 0

"^" という正規表現は行の先頭に (それが空行であっても) マッチします。|:move| コ
マンドはマッチした行を仮想的な 0 行目の下に移動します。つまり、マッチした行が
ファイルの先頭行になります。|:global| コマンドは行番号が変更されても処理を継続
できます。そして、マッチしたすべての行が、順番にファイルの先頭に移動していきま
す。

ある一定の範囲だけ並べ替えることもできます。まず、並べ替えたい範囲の一行上に移
動し、"mt" でマークします。そして、範囲の末尾に移動し、次のように入力します: >

	:'t+1,.g/^/m 't

==============================================================================
*12.5*	単語を数える

ときには、単語数に制限のある文章を書かなければならない場合もあるでしょう。Vim
には単語を数えるための機能があります。
ファイル全体の単語数を数えるには、次のコマンドを使います: >

	g CTRL-G

"g" の後の空白は入力しないでください。この空白はコマンドを読み易く表記するため
のものです。
次のような結果が出力されます:

	列 1 / 0; 行 141 / 157; 単語 748 / 774; バイト 4489 / 4976 ~

これを見れば、何番目の単語 (748) にカーソルがあり、ファイル全体でいくつの単語
(774) があるのかがわかります。

ファイルの一部の文章についてのみ単語を数えたい場合は、テキストの先頭に移動して
"g CTRL-G" を入力し、テキストの末尾に移動して "g CTRL-G" をもう一度入力し、そ
して、表示された単語の位置を引き算して単語数を求めます…これは頭の体操にはなり
ますが簡単な方法とは言えませんね。ビジュアルモードを使えば、テキストを選択して
から "g CTRL-G" を入力するだけです。次のような結果が表示されます:

	選択 5 / 293 行; 70 / 1884 単語; 359 / 10928 バイト ~

単語や行などを数える他の方法については |count-items| を参照してください。

==============================================================================
*12.6*	マニュアルを引く				*find-manpage*

シェルスクリプトや C プログラムを書いているときに、コマンドや関数のマニュアル
を引きたいことがあると思います (Unix での話です)。まずは簡単な方法でやってみま
しょう。ヘルプを引きたい単語の上にカーソルを移動して、次のコマンドを入力しま
す: >

	K

単語を引数として "man" プログラムが実行され、マニュアルが見つかった場合は、そ
れが表示されます。テキストをスクロール表示するために、標準設定のページャ (おそ
らく "more" プログラム) が使われます。マニュアルを最後まで表示したら、<Enter>
を押して Vim に戻ってください。

この方法の欠点は編集中のテキストとマニュアルを同時に表示できないことです。しか
し、Vim ウィンドウの中にマニュアルを表示する方法もあります。最初に、man ファイ
ルタイププラグインをロードしてください: >

	:runtime! ftplugin/man.vim

このコマンドを vimrc ファイルに書いておけばいつでも使えるようになります。さて、
":Man" コマンドが使えるようになりました。新しいウィンドウにマニュアルを表示で
きます:
>
	:Man csh

カラー表示されたテキストをスクロールして表示することができます。これで、調べた
い説明を見つけることができますね。CTRL-W w を使えば、元のウィンドウにジャンプ
できます。
特定のセクションのマニュアルを表示したいときは、セクション番号を指定してくださ
い。例えば、セクション 3 にある "echo" を調べるなら、次のようにします: >

	:Man 3 echo

マニュアルの中で "word(1)" のような形式で示されている他のマニュアルにジャンプ
するには CTRL-] を押してください。":Man" コマンドが続けて使われた場合は、同じ
ウィンドウが使用されます。

カーソル下の単語のマニュアルを表示するには、次のコマンドを使います: >

	\K

(自分で <Leader> を再定義している場合は、"\" ではなく、それを使ってください)
例えば、次の行を編集中に "strstr()" の戻り値を知りたくなったら:

	if ( strstr (input, "aap") == ) ~

"strstr" の上にカーソルを移動し、"\K" と入力してください。ウィンドウが開いて
strstr() のマニュアルが表示されます。

==============================================================================
*12.7*	空白を取り除く

行末の空白は無用であり、浪費であり、見苦しいものであると考える人々がいます。す
べての行末から空白を取り除くには、次のコマンドを使います: >

	:%s/\s\+$//

"%" を使ってすべての行を範囲指定しています。":substitute" コマンドに指定されて
いるパターンは "\s\+$" です。これは、空白文字 (\s) が一文字以上続き (\+)、行末
($) で終わる文字列にマッチします。このようなパターンの書き方は |usr_27.txt| で
説明されています。"to" の部分は空 ("//") になっています。空文字列で置き換える、
つまり、マッチした空白を削除するという意味になります。

もう1つの浪費パターンとして、tab の直前にスペースが使われている場合があります。
たいていは、そのスペースを削除しても見た目の空白の量は変わりませんが、いつも大
丈夫というわけではありません。ですから、手作業で削除するのがベストです。次の検
索コマンドを使ってください: >

	/ 	

何も見えないかもしれませんが、Tab 文字の直前にスペースがあります。つまりこれは
"/<Space><Tab>" です。検索したら、"x" コマンドを使ってスペースを削除し、見た目
の変化がないことを確認してください。変化があった場合は、tab 文字を挿入して調整
しましょう。"n" を押して次の場所を検索します。マッチするものがなくなるまで同じ
操作を繰り返してください。

==============================================================================
*12.8*	単語が使われている場所を検索する

UNIX を使っているなら、Vim と grep コマンドを組み合わせれば、指定した単語が含
まれているすべてのファイルを開くことができます。これは、プログラムを書いている
ときに、特定の変数が使われているファイルを表示または編集したい場合にとても便利
です。
例えば、"frame_counter" という単語が含まれているすべての C 言語ファイルを開く
には、次のようにします: >

	vim `grep -l frame_counter *.c`

このコマンドを詳しく見てみましょう。"grep" コマンドは、指定されたファイルの中
から単語を検索します。"-l" 引数が指定されているので、単語が含まれているファイ
ルの名前だけが表示されます。マッチした行は表示されません。検索される単語は
"frame_counter" です。単語の指定には正規表現が使えます。(Note: grep で使える正
規表現は Vim の正規表現と完全に同じではありません。)
コマンドはバッククォート (`) で囲まれています。これは、コマンドを実行し、その
出力を、コマンドラインに入力されたものとして扱うように UNIX シェルに指示してい
ます。つまり、grep コマンドが実行され、出力されたファイルの一覧が Vim の引数に
渡されます。Vim が起動した後は、":next" や ":first" などのコマンドでそれらの
ファイルを切り替えられます。


単語が使われている行を検索する
------------------------------

上述のコマンドは単語が含まれているファイルを見つけるだけなので、単語が使われて
いる行は自分で検索する必要がありました。
Vim には、指定された文字列を複数のファイルの中から検索するための組み込みコマン
ドがあります。例えば、"error_string" という文字列をすべての C 言語ファイルの中
から検索するには、次のコマンドを使います: >

	:grep error_string *.c

指定されたファイル (*.c) の中から、"error_string" という文字列が検索されます。
コマンドを実行すると、文字列が含まれている最初のファイルが開き、検索にヒットし
た最初の行にカーソルが移動します。文字列が現れる次の場所 (同じファイルとは限り
ません) に移動するには、":cnext" コマンドを使います。一つ前に戻るには ":cprev"
コマンドを使います。":clist" コマンドを使うと、検索結果の一覧と現在位置が表示
されます。
":grep" コマンドの実行には、外部プログラムの grep (Unix) または findstr
(Windows) が使われます。使われるプログラムは 'grepprg' オプションで変更できま
す。

==============================================================================

次章: |usr_20.txt|  コマンドラインを素早く入力する

Copyright: see |manual-copyright|  vim:tw=78:ts=8:noet:ft=help:norl:
