SmartHR Tech Blog

SmartHR 開発者ブログ

textlintへのルール追加に必要な正規表現を、やさしく解説してみた

textlintへのルール追加に必要な正規表現を、やさしく解説してみた

こんにちは、UXライターのkunyです。3月にスケボーを始めて、最近チックタックができるようになりました。

さてSmartHRでは、textlintに独自のルールプリセットを追加して利用しています。ルールプリセットはオープンソースで公開しており、継続的にルールを追加しています。

さて、そのルール追加の際に正規表現の知識が必要なのですが、「正規表現、マジ難しい...」と感じています。「う〜ん」と唸りながらルールを追加することも多いです。

そこで自分の勉強も兼ねて、textlintへのルール追加の際に必要な「基本的な正規表現」を、実例とセットでまとめてみました。「ブログ書くぞ〜」と宣言したところ、少数ながらも「いいね」をいただき、需要あるかも?と思っています。感想やフィードバックを、Twitterでつぶやいていただけると嬉しいです。

なおSmartHRには、Airtableに記述したルールをtextlintに反映する仕組みがあるので、正規表現さえわかれば誰でもルールを追加できます(この仕組み、すばらしい...!)。

textlintのルール追加で、よく使う6つの正規表現

ここから本題ですが、textlintにルールを追加するために最初に覚えるとよい正規表現をまとめてみました。最低限この6つを把握するだけでも、正規表現に対する苦手意識が消えるんじゃないでしょうか?

# 正規表現 意味
1 AAA|BBB|CCC |で区切った文字列のいずれか一つ りんご|みかん|バナナ
→りんご or みかん or バナナ
2 [ABC] []内のいずれか一文字 [山川海]
→山 or 川 or 海
3 (AAA) ()内の文字列をグルーピング
※あとから取り出すことも可能
(HH)時(MM)分
→HH, MM
4 $1,$2,,, ()でグルーピングされた文字列を、順に取り出す
5 ?<! 文字列の直前に、?<!で指定した表現がある場合を除く(否定後読み) (?<!相撲)取り
→「取り」は検知し、「相撲取り」は検知しない
6 ?! 文字列の直後に、?!で指定した表現がある場合を除く(否定先読み) 腕(?!相撲)
→「腕」は検知し、「腕相撲」は検知しない

6つの正規表現の使いどころを、実例で解説

どのように正規表現を使ってtextlintにルールを追加するか、実例をもとに解説します。

例1. 「従業員様」「お客様」を検知して、「従業員さま」「お客さま」を推奨するルールを追加したい

前提として、SmartHRのライティングガイドラインには「平仮名にしたほうが読みやすい漢字は平仮名にする」という原則があります。この原則に沿うと「〇〇様」よりも「〇〇さま」の表記を推奨することになり、これをtextlintのルールとして記述する手順を説明します。

まず、「様」の代わりに「さま」を推奨するように、expected(推奨したい文字列)・pattern(検知したい文字列)を記述します。

rules:
  - expected: さま
    pattern: 様

このままだと、例えば「様々」も検知されてしまって、「さま々」が推奨されてしまいますね。そこで、「従業員様」と「お客様」だけを検知するため正規表現を使います。前述の#1と#3を参考に、patternに(従業員|お客)を追記し、//で囲みます。

rules:
  - expected: さま
    pattern: /(従業員|お客)様/

「従業員さま」「お客さま」を推奨したいので、patternの()内の記述を、expectedで取り出せるように#4を参考に$1を指定します。これで「従業員さま」「お客さま」を推奨するルールが完成しました。

rules:
  - expected: $1さま
    pattern: /(従業員|お客)様/

補足:「従業員様」「お客様」を別々に検知すれば、正規表現は不要です。ただルールを1つにまとめていると、あとで別パターンを追加するときに楽です。例えば、追加で「皆様」を検知したい場合にメンテナンスが容易です。

例2. 「紐付く」を検知して、「紐づく」を推奨するルールを追加したい

いきなりですが、「紐付く」は動詞ですね。動詞には活用形があるので、正規表現を使ってあわせて検知対象にするといいでしょう。具体的には「紐付いた」「紐付かない」「紐付き」「紐付ける」も検知できるようにします。(ちなみに、活用形を調べるには日本語の動詞の活用形を利用すると便利です)

まず「紐付く」の代わりに「紐づく」を推奨するよう記述してみます。#3を参考にpatternに()を、#4を参考にexpectedに$1を指定して、以下のように書きます。

rules:
  - expected: 紐づ$1
    pattern: 紐付(く)

「紐付」のあとに「い」「か」「き」「け」が続く場合も検知したいので、#2を参考に「い」「か」「き」「け」を追記して[]で囲みます。これで、必要なパターンを網羅したルールが完成しました。

rules:
  - expected: 紐づ$1
    pattern: /紐付([いかきくけ])/

例3. 「後で」を検知して「あとで」を推奨するルールを追加したい

一見、正規表現は不要そうですね。まず、正規表現を使わずにルールを記述します。

rules:
  - expected: あとで
    pattern: 後で

ここでコード内を検索したり、想像力を働かせると、「直後で」「開始後で」「終了後で」などの文字列も検知されることに気づきます。このままだと、「直あとで」「開始あとで」が推奨されてしまうので、正規表現でこれらを検知対象から除外します。

まず、「直後で」を除外します。#5を参考に?<!で「直」を指定し、#3の()で囲むことで、「直後で」という場合を除いて「後で」を検知できます。

rules:
  - expected: あとで
    pattern: (?<!直)後で

次に、#2の[]を使って、「始後で」「了後で」も除外します。以下の表現で、「後」の直前の一文字が「直」「始」「了」の場合を除いて、「後で」が検知できるようになりました。

rules:
  - expected: あとで
    pattern: (?<![直始了])後で

例4. 「振込」を検知して「振り込み」を推奨するルールを追加したい

この記事で紹介する最後の例です。あと一息なのでがんばりましょう(ブログを書いている自分に対しての応援)。

まずは、正規表現を使わずにルールを記述します。

rules:
  - expected: 振り込み
    pattern: 振込

このままだと「給与振込」など「振込」を含む名詞も検知されます。

原則として名詞に送り仮名は付けないので、「振込」を含む名詞を検知対象外にします。また、SmartHRには「給与明細・賞与明細を従業員に配布する機能」があり、コード内に「給与振込口座」の文字列があります。

そこで「給与振込」「振込口座」「給与振込口座」を検知対象外にするため、#3,5,6を参考に、patternに(?<!給与)(?!口座)を追記します。これで、意図通りに検知できるようになりました。

rules:
  - expected: 振り込み
    pattern: /(?<!給与)振込(?!口座)/

最後に

効率的なtextlintへのルール追加には、もう少し高度な正規表現が必要ですが、最低限おさえるとよい正規表現を解説してみました。

この記事で解説した正規表現は、SmartHRの独自ルールを記述したファイルで確認できるので、気になる方はチェックしてみてください。また、SmartHRで働くことに興味をもっていただいた方がいたら、お気軽にカジュアル面談をお申し込みください!

それでは皆さま、素敵なtextlintライフを!