単独eval読書会#03

第3回は文字列です.正規表現も(やや不親切ですが)少し触れます.

概要

" 結合は . を使用する
echo 'hello ' + 'world'
" 0
echo 'hello ' . 'world'
" hello world


" 結合・分割
echo join(['hello', 'world'], ',')
" hello,world
echo split('foo:bar:baz,', ':')
" ['foo', 'bar', 'baz']


リストの様な操作で一部分を取り出すことができます.インデックスはCと同じように0からです.

let str = '0123456789'
" 文字列の長さ
echo strlen(str)
" 10

echo str[0]
" 0
echo str[4]
" 4

echo str[10]
" (何も表示されない)

echo str[3:6]
" 3456 (4番目から6番目まで)
echo str[3:-4]
" 3456 (4番目から,後ろから4番目まで)

echo str[3:]
" 3456789 (範囲指定では省略可能)
echo str[:6]
" 0123456
echo str[:]
" 0123456789 (strと同じ)

echo strpart(str, 3)
" 3456789 (4番目から最後まで)
echo strpart(str, 3, 6)
" 345678 (4番目から6文字)

その他組み込み関数

変換関係

" 文字 - ASCII
echo char2nr('A')
" 65
echo nr2char(65)
" A

" 文字列 - 数値
echo str2nr('-25')
" -25 (数値として)
echo str2nr('A32')
" 0   (変換できない場合0となる)


echo tolower('HELLO')
" hello (小文字に変換)
echo toupper('hello')
" HELLO (大文字に変換)

" エスケープ
let str = 'That''s right'
echo str
" That's right
echo shellescape(str)
" 'That'\''s right'
echo fnameescape("/home/user/My Document")
" /home/user/My\ Document

正規表現関係

matchとsearchがあります.matchは渡した引数がマッチするかどうか,
searchはカレントバッファ上でヒットした物をマッチする場所を探す関数です.
ここではmatchだけを取り上げます.

"setlocal magic (setを使うべき:追記参照)

let str = 'hello world'
let pat = '\S*$'

echo str =~# pat
" 1 (マッチしたら1)
echo match(str, pat)
" 6 (マッチした最初の位置)
echo matchend(str, pat)
" 11 (マッチした最後の位置)
echo matchstr(str, pat)
" world (マッチした文字列)

'magic'がセットされているかどうかでマッチの挙動が若干変わります.
たとえば.を単純に文字としてヒットさせるか,正規表現として何か1文字にヒットさせるかの様な違いです.
matchはヒットした最初の位置(マッチしない場合は-1)を返すので,
if match()とすると意図した結果になりません.かならず=~#か=~?を使用しましょう.
magicの設定に寄らず適切なマッチを行いたい場合,\vなどを使用します(:help /magic).
追記: match()の挙動をよく理解していませんでした.match()では'magic'がオン,'cpoptions'がオフとして比較を行います.

\v \m \M \V マッチするもの
$ $ $ \$ 行末
. . \. \. 何か1文字
* * \* \* 直前のアトムの繰り返し
() \(\) \(\) \(\) グループ化してアトムにする
| \| \| \| 選択の区切り
\a \a \a \a 英字
\\ \\ \\ \\ リテラルのバックスラッシュ
\. \. . . リテラルのドット
\{ { { { リテラルの "{"
a a a a リテラルの 'a'

" ふたつは同じ意味
let patm = '\ml.o'
let patM = '\Ml\.o'

量指定子などは他の言語とは異なる部分が多いのでhelp: pattern-searchesを参照すると良いです.
なお,パターンを作成するときはダブルクォーテーションではエスケープが面倒なのでできるだけシングルクォーテーションを使うようにしましょう.

"setlocal magic (setを使用するべき: 追記参照)

" ふたつは同じ意味
let pat0 = '\(.\{-}\)\(bb\)\(.*d\)'
let pat1 = "\\(.\\{-}\\)\\(bb\\)\\(.*d\\)"

追記: (コメントより)'magic'はグローバルオプションでした(help: 'magic').setlocalを用いても一応グローバルオプションとして設定可能ですが,混同するので使用は控えるべきでしょう.
=~やmatch()は常に'magic'をオン,'cpoptions'を空にした状態で行われる様ですので,特に気にしなくて良さそうです.というわけでsetlocal行はコメントアウトしておきました.
それと,vimのhelp的にはオプションを''で括った方が良さそうですね.


毎回訂正いただいて大変感謝してます.ボクはちゃんとhelp読むように….