この記事は Vim 8.0 Advent Calendar の 17 日目の記事です。
Vim 8.0 では新しく便利な組み込み関数が多数追加されています。今回はその中から、文字列操作に関連するものを紹介します。
matchstrpos({expr}, {pat}[, {start}[, {count}]])
Vim script には元々、指定した文字列から、正規表現にマッチした位置を取り出す match()
関数と、マッチした文字列を取り出す matchstr()
という関数があります。
これら関数は便利ですが、マッチした位置とマッチした文字列両方が欲しい場合には少し問題があります。この場合、それぞれの関数を呼び出すことになるのですが、関数を 2 回呼び出すのは手間がかかる上に、同じ正規表現マッチを 2 回行うのはパフォーマンス的にも無駄です。
そこで、matchstrpos()
関数が追加されました。引数は match()
関数や matchstr()
関数と同じで、戻り値が違います。"マッチした文字列"、"マッチした先頭の位置"、"マッチした末尾の位置" の 3 要素の配列を返します。
echo matchstrpos('fizz buzz fizzbuzz', 'b\w\+')
" => ['buzz', 5, 9]
strcharpart({src}, {start}[, {len}])
Vim script には元々、文字列の一部を切り出す strpart()
関数がありますが、これはバイト単位で動作するため、マルチバイト文字に対して使うと文字列のバイトの途中で切り取られてしまうという問題がありました。
そこで strcharpart()
が追加されました。これはバイト単位ではなく、文字単位で文字列の一部を切り取ります。
echo strcharpart('あいうえお', 1, 3)
" => いうえ
strgetchar({str}, {index})
文字列内の指定した index の文字の文字コードを取得します。これはバイトではなく文字単位で動作します。文字数はマルチバイトで数えられ、結果はマルチバイト文字の 1 文字の文字コードになります。
let code = strgetchar('あいうえお', 4)
echo printf('0x%x', code)
" => 0x304a
echo nr2char(code)
" => お
byteidxcomp({expr}, {nr})
Vim script には byteidx()
という関数があります。これは、マルチバイト文字を考慮して、{expr}
に与えた文字列の 0 オリジンで {nr}
番目の文字が、文字列内の何バイト目かを返します。{nr}
が文字列の文字数と同じ場合は文字列全体のバイト数を返し、{nr}
がそれより大きい場合は -1 を返します。
echo byteidx('あいうえお', 2)
" => 6
echo byteidx('あいうえお', 5)
" => 15
echo byteidx('あいうえお', 6)
" => -1
新しく追加された byteidxcomp()
は、合成文字を個別にカウントします。
let s = 'e' . nr2char(0x301)
echo s
" => é
echo byteidx(s, 1)
" => 3 (合成文字を 1 文字とみなし、文字列が 1 文字であるため文字列全体のバイト数を返します)
echo byteidx(s, 2)
" => -1 (合成文字を 1 文字とみなし、{nr} が文字数より大きいため -1 を返します)
echo byteidxcomp(s, 1)
" => 1 (合成文字を別々の文字とみなし、"e" までをカウントして 1 を返します)
echo byteidxcomp(s, 2)
" => 3 (合成文字を別々の文字とみなし、文字列が 2 文字であるため文字列全体のバイト数を返します)
glob2regpat()
glob()
関数などで使われる、いわゆるワイルドカードなどが含まれるファイルパターンを正規表現に変換します。
echo glob2regpat('*.vim')
今のところ、ワイルドカードの *
も **
も、正規表現の .*
に変換されるようです。実際のワイルドカードの *
はディレクトリを辿らず、/
などのディレクトリ区切り文字にはマッチしないため、若干挙動が異なってしまう点に注意してください。