Vim scriptのmatchstr()関数を使用する際の注意点

Vim script Advent Calendarはもう終了してしまいましたが、 Vim scriptのmatchstr()関数を使用する際に注意した方が良いと思った事があったので共有します。

結論

いきなり結論から言うと、マッチ結果が空文字となる可能性のあるパターンを指定すると失敗した場合との判定ができない、という事です。
例えば

echo matchstr('abc', 'z\?')

このコマンドの出力結果は空文字となりますが、それはマッチが失敗している訳ではありません。
abcにzという文字は含まれませんが、\?は存在しない場合もマッチするので、マッチは成功しているのです。
しかし、マッチした部分文字列は空文字となるため、matchstr()関数の失敗ケースの戻り値と判断がつかないため、次のようなコードは意図が違ってきてしまいます。

if matchstr(str, pattern) !=# ''
    " match!
    ...
endif

解決策

解決策として、match()関数やmatchlist()関数を使えば問題ありません。
両方ともマッチ失敗時の戻り値と成功時の戻り値が重なる事はないからです。

if match(str, pattern) !=# -1
    " match!
    ...
endif

if !empty(matchlist(str, pattern))
    " match!
    ...
endif

マッチ文字列が空文字とならないと分かる場合はmatchstr()関数を使っても構わないですが、 上記コードのように変数で渡ってくる場合何の値が入るか読めない事もあるため、個人的にはmatchstr()関数は使わない方がいいと思いました。

終わり

matchstr()関数のコードについては至極当然と思う方もいるかもしれませんが、Advent Calendarって*1もともとTips的な事でもいいから共有する風潮もあったりしたよな、と思ったので。
それにこういう事例を共有してあー俺もやってたわ気を付けようって人が1人でもいるかもしれませんしね。
あと今年はQiitaのシステム上、Advent Calendarが25日までなのでその分ドタキャンやこういう小さなTips系記事が少なかった気がしますね。
それに小さな事でもコード書いて共有するべきだと思ったので、やはり記事を書こうという気になった次第です。

関連リンク

*1:Advent Calendarじゃないけど。間に合ってないけど。