HAKADORI その他

正規表現で日付を検索

2019.11.16 土

ニシムクサムライ

こんにちは、CMB室の藤田です。

今回は、日付(「mmdd日」形式)を正規表現で検索する方法を考えてみました。
InDesign ストーリーテキスト内の「○月●日」という日付文字列を指定する正規表現スタイル作成が目的です。

以下の表は日付一覧マトリクスです。横が 112月の月名 、縦が 131日の日名 です。便宜上、実際には存在しない日付も記入されています。

日付マトリクス

● とりあえず数字と日付で検索させる

・1桁の数字

単純に 数字数字 で検索するのであれば

ですが、これでは1桁の数字しか検索できません。

\d月\d日

正規表現スタイルに「\d月\d日」を設定

・2桁の数字

上記の数字文字列を1桁以上2桁までの数字として検索するのであれば

ですが、これだと2桁までの数字がなんでもマッチしてしまいます。

\d{1,2}月\d{1,2}日

正規表現スタイルに「\d{1,2}月\d{1,2}日」を設定

 

例えば、「230」、「16」、「99」、「00」など存在しない日付にもマッチしてしまいます。

日付を検索するなら、1月〜12月各月のしかるべき日数を指定する必要があります。

● ニシムクサムライ

月ごとの日数を判別する方法で「ニシムクサムライ」という語呂合わせがあります。
漢字で書くと「サムライ」、つまり2・4・6・9・11月は他の月と日数が違う(31日ではない)ことを判別する語呂合わせです。「」という当て字も通販番組の電話番号みたいですがまあ理解できます。ただ「士」という字を分解して「十一」、サムライが11に変換されるというのはいささか強引な気が…語呂合わせの世界ではフレキシブルな解釈が必要です。

士(サムライ)

士は11と解釈

● 1か月の日数が31日の月

1・3・5・7・8・10・12月は1か月の日数が31日です。

・31日の月編

1・3・5・7・8は1桁数字なので角括弧 [...] で囲むことでそれぞれの数字いずれかにマッチする1文字が組み立てられます。

さらに、2桁の数字文字列 10・12 と丸括弧 (…) でくくってグループ化し、それぞれの単語を縦棒 | で区切ることでマッチする文字列が組み立てられます。

・31日の日編

1から31という数字をマッチさせるので [1-31] にすればいいかと思ってしまいがちですがそうではありません(※「1・2・3」いずれかの1文字しかマッチしません)。日付を文字としてパターン分解する必要があります。

日付 正規表現 意味
1から9まで [1-9] 一の位が1から9
10から29まで [12][0-9] 十の位が1または2で、一の位が0から9
30と31 3[01] 十の位が3で、一の位が0または1

これらを丸括弧 (…) でくくってグループ化し、それぞれの単語を縦棒 | で区切ることで1から31の日付文字列にマッチする文字列が組み立てられます。

上記の月日の正規表現を合わせることで1か月の日数が31日の月を検索する正規表現ができます。その前に、少し工夫して日付の前の文字が数字ではない条件を付け加えます。

否定後読みの条件です。これを前に付け加えます。

1か月の日数が31日の月

正規表現スタイルに「(?<![0-9])([13578]|10|12)月([1-9]|[12][0-9]|3[01])日」を設定

 

これで、1か月の日数が31日の月の日付を検索する正規表現ができました!

● 1か月の日数が30日の月

ニシムクサムライ」のうち4・6・9・11月は1か月の日数が30日です。

・30日の月編

4・6・9は1桁数字なので角括弧 [...] で囲むことでそれぞれの数字いずれかにマッチする1文字が組み立てられます。

さらに、11 も丸括弧 (…) でくくってグループ化し、それぞれの単語を縦棒 | で区切ることでマッチする文字列が組み立てられます。

・30日の日編

こちらも日付を文字としてパターン分解する必要がありますが、1か月の日数が31日の月でつくったパターンを改変するだけです。

日付 正規表現 意味
1から9まで [1-9] 一の位が1から9
10から29まで [12][0-9] 十の位が1または2で、一の位が0から9
30 30 十の位が3で、一の位が0

これらを丸括弧 (…) でくくってグループ化し、それぞれの単語を縦棒 | で区切ることで1から30の日付文字列にマッチする文字列が組み立てられます。

上記の月日の正規表現を合わせることで1か月の日数が31日の月を検索する正規表現ができます。こちらも、日付の前の文字が数字ではない否定後読みの条件を付け加えます。

1か月の日数が30日の月

正規表現スタイルに「(?<![0-9])([469]|11)月([1-9]|[12][0-9]|30)日」を設定

 

これで、1か月の日数が30日の月の日付を検索する正規表現ができました!

● 2月

2月は1か月の日数が28日ですが、うるう年も考慮して29日で組み立ててみます。

・2月の月編

こちらはそのままです。

・2月の日編

2月も日付を文字としてパターン分解する必要がありますが、上で作成した31日30日の日パターンから30以降を取るだけです。

日付 正規表現 意味
1から9まで [1-9] 一の位が1から9
10から29まで [12][0-9] 十の位が1または2で、一の位が0から9

これらを丸括弧 (…) でくくってグループ化し、それぞれの単語を縦棒 | で区切ることで1から29の日付文字列にマッチする文字列が組み立てられます。

上記の月日の正規表現を合わせることで2月の日付を検索する正規表現ができます。こちらも、日付の前の文字が数字ではない否定後読みの条件を付け加えます。

2月

正規表現スタイルに「(?<![0-9])2月([1-9]|[12][0-9])日」を設定

 

これで、2月の日付を検索する正規表現ができました!

● すべてを結合

あとは、これら3つを丸括弧 (…) でくくってグループ化し、それぞれの単語を縦棒 | で区切ることで日付文字列にマッチする文字列が組み立てられます。

日付を検索する正規表現

正規表現スタイルに「(?<![0-9])(2月([1-9]|[12][0-9])日|([469]|11)月([1-9]|[12][0-9]|30)日|([13578]|10|12)月([1-9]|[12][0-9]|3[01])日)」を設定

 

これで日付を検索する正規表現ができました!
実際はこんなにややこしいことはしないかもしれませんが、日付表記は普遍的なものなので汎用性はあるかもしれません?

-HAKADORI, その他
-, ,