Help us understand the problem. What is going on with this article?

正規表現を理解してみる

はじめに

これは、静岡 Advent Calendar 2019の3日目の記事となります。

今年は勉強会には2019/1/26(土)に「DevLOVE静岡」しか参加していないので勉強会のことは書きにくい。
一応、Qiitaは技術系ブログなので静岡にまつわる(名産品や地名など)なら何でもいいかなと、ネタとして2012年に静岡Developers勉強会で「JavaScriptの正規表現」のセッションを引っ張り出して、これをQiita用に書き直してみました。

正規表現

正規表現ってなに?
正規表現とは、簡単に言えば 検索や置換をより便利にするものです。
例えば文章中に 「りんご」 と 「みかん」 を検索したいとき、別々に検索するのは手間だし面倒です。
正規表現で検索に使うキーワードを以下のように書くと

 りんご|みかん

「りんご」と「みかん」を同時に検索する事が出来ます。

javascript 正規表現 チートシート
http://visibone.com/products/bbk14-15_850.jpg

オンライン上の正規表現の確認サイト

正規表現で使用する特殊文字

「|」を使うと複数キーワードで検索できるように、下記の特殊文字には役割がある。

 ¥ / [ ] - ( ) ? + * | . ^ $

 
正規表現では「メタ文字」と呼んでいる。
メタ文字自身を検索対象とする場合、¥を付ける

例 ¥¥ ,¥[ , ¥+

任意の1文字と位置指定

「.」…とにかくなんでもいい1文字(改行以外)

正規表現 み.
対象文字 みん みん み

「^」…先頭にマッチ 呼び名:ハット

正規表現 ^みかん
対象文字 みかん みかん みかん

「$」…末尾にマッチ

正規表現 みかん$
対象文字 みかん みかん みかん

同じ文字の繰り返し

「*」…直前の文字を 0 回以上にマッチ

正規表現 おー*い  ※数量詞表現: おー{0,}い
対象文字 おい おーい おーーい

「+」…直前の文字を 1 回以上にマッチ

正規表現 おー+い ※数量詞表現: おー{1,}い
対象文字 おい おーい おーーい

「?」…直前の文字を 0 回又は 1 回にマッチ

正規表現 おー?い ※数量詞表現: おー{0,1}い
対象文字 おい おーい おーーい

「.*」 …なんでもいい文字の連続(最長)

正規表現 JR.*
対象文字 JR静岡駅から浜松駅まで
※可能な限り合致するまでヒットする

「.*?」…なんでもいい文字の連続(最短)

正規表現 JR.*?
対象文字 JR静岡駅から浜松駅まで
※可能な限り少ない回数でヒットする

パターン論理和とパターングループ

「|」…いずれかの文字列(論理和)

正規表現 みかん|りんご
対象文字 ばなな みかん ぶどう りんご

「()」…グループ化(先優先)

()を付けた場合の違い
正規表現 私はみかん|りんごが好きです
対象文字 私はみかんが好きです
対象文字 私はりんごが好きです

正規表現 私は(みかん|りんご)が好きです
対象文字 私はみかんが好きです
対象文字 私はりんごが好きです

数詞とパターングループ

「{}」…数量詞

正規表現 w{3} 直前の文字を n 回にマッチ
対象文字 www.ora.com/goodparts/ww

正規表現 w{2,} 直前の文字を n 回以上にマッチ
対象文字 www.ora.com/goodparts/ww

正規表現 w{0,3} 直前の文字を n 回以上、m 回以下にマッチ
対象文字 www.ora.com/goodparts/ww

「()」…グループ化

正規表現 (じゃ)+ーん
正規表現 (じゃ){1,}ーん ※数量詞に置き換えた場合
対象文字 じゃーん じゃじゃーん じゃじゃじゃーん

数量詞の補足

繰り返し回数
正規表現 (みかん){2,4}
対象文字 みかんみかんみかんみかんみかん
※指定した回数より多く繰り返している場合には 繰り返し回数の上限までマッチする。

正規表現 (みかん){2,4}
対象文字 みかんみかんみかん
※可能な限り多い回数でマッチする。

正規表現 (みかん){2,4}
対象文字 みかんみかんみかんみかんみかんみかん
※5 個以上は、パターンの繰り返しでマッチする。

文字クラス

「[]」…指定内の任意表現 呼び名:ブラケット

正規表現 今日の天気は[晴曇雨]です
対象文字 今日の天気はです
対象文字 今日の天気はです
対象文字 今日の天気はです
対象文字 今日の天気は雪です

「[^]」…指定内の任意以外表現

正規表現 今日の天気は[^晴曇雨]です (^が先頭)
対象文字 今日の天気はです

※[]の中で ^ が使用された場合は、行の先頭を表す ^(ハット)とは意味が異なります。

[] と (|) の使い方を間違えた場合

例 [りんご|みかん]
「り」「ん」「ご」「|」「み」「か」「ん」のどれか一文字という意味になる。
regex101_2.png

文字クラス内の記述

  • 「[A-Z]」…英大文字 A から Z までのどれか
  • 「[a-z]」…英小文字 a から z までのどれか
  • 「[0-9]」…数字 0 から 9 までのどれか
  • 「[A-Za-z0-9]」…上記を連続して書ける
  • 「[あ-お]」…あお のどれか
  • 「[か-こ]」…かこ のどれか
  • 「[.*]」…. か * のいずれかの文字 ※[]の中ではメタ文字は普通の文字として認識される文字もメタ文字ではない。 (但し、先頭の^や ] や範囲指定の‐は例外)

主な特殊文字

  • 「¥w」…英字、数字、アンダースコア。 [a-zA-Z0-9_] と同じ
  • 「¥W」…英字、数字、アンダースコア以外の文字。 [^a-zA-Z0-9_]と同じ
  • 「¥d」…数字。[0-9] と同じ
  • 「¥D」…数字以外の文字。[^0-9]と同じ。
  • 「¥n」…改行
  • 「¥s」…スペース(全角スペースも対象)
  • 「¥S」…スペース(全角スペースも対象)以外の文字

主な正規表現の使用例

日付を検索する

正規表現 \d{4}\/\d{1,2}\/\d{1,2}
対象文字 2019/12/20 2019/12/2

郵便番号を検索する(厳密ではない)

正規表現 \d{3}-\d{4}
対象文字 012-1234

メールアドレスを検索する(厳密ではない)

正規表現 ^[\w_-]+@[\w¥.-]+.\w{2,}$
対象文字 microsoft@e-mail.microsoft.com

正規表現の修飾子

「/g」…Global (複数回マッチする)

正規表現 /みかん/g
対象文字 みかん りんご みかん

「/i」…Insensitive (大文字小文字を区別しない)

正規表現 /ABC/i
対象文字 abcdef

「/m」… Multiline (^ と $ が行末記号にマッチ)

正規表現 /456/m
対象文字 123¥n456¥n789
※¥n:改行

正規表現グループ

多くの正規表現エンジンでは「( )」を使ったキャプチャ(マッチした文字列の捕捉)をサポートしています。「$(番号)」でマッチした文字列を順番に取得できます。

キャプチャ

xx = "12:34:56".match(/(\d+):(\d+):(\d+)/);
document.write(RegExp.$1 + "<br>");    // → 12
document.write(RegExp.$2 + "<br>");    // → 34
document.write(RegExp.$3 + "<br>");    // → 56

非キャプチャ

「(?:)」を使うことでキャプチャを外します。

xx = "12:34:56".match(/(?:\d+):(\d+):(\d+)/);
document.write(RegExp.$1 + "<br>");    // → 34
document.write(RegExp.$2 + "<br>");    // → 56

肯定先読み

リンカーンの「人民の人民による人民のための政治」というフレーズ
正規表現 人民
対象文字 人民人民による人民のための政治
人民が3つ抽出されました。

肯定先読みを使用します。
正規表現 人民(?=による)
対象文字 人民の人民による人民のための政治

人民が3つありますが、肯定先読み(?=による)をつけることで「による」が含まれる「人民」だけがマッチしたということです。ここでポイントなのは、マッチした「による」が結果に含まれていないことです。
肯定先読みは後に特定の言葉を含んでいる条件を満たす文字列のみを抽出したいという時に使えます。

参照:肯定先読み~否定後読み

否定先読み

肯定先読みの逆になります。「による」が含まれる「人民」以外が抽出されます。

正規表現 人民(?!による)
対象文字 人民の人民による人民のための政治

文字列の否定

[^ABC]*? … 文字1つ1つを除外

正規表現 JR[^静岡]*?駅
対象文字 JR静岡駅 JR浜松駅 JR三島駅 JR山駅
これだとJR岡山駅があると対象外となる

((?!ABC).)? … 文字列を除外 (?!ABC).?に変更

正規表現 JR((?!静岡).)*?駅
対象文字 JR静岡駅 JR浜松駅 JR三島駅 JR岡山駅
これだとJR東静岡駅を含めた場合、JR東静岡駅も対象外となってしまう

最後に

当初は静岡のIT勉強会について何か書こうと思ったのですが、あまり過去を振り返っても仕方ないし未来志向にしようと。

ここ数年は低活動状態なので勉強会を検索するとかもしてなかったので、いつの間にか静岡でも結構勉強会やってたんだなというのを記事を書く上で検索して今頃知るくらいです。行こうかなと思ったら出勤日でした残念。
"11月か12月を目処に「人工知能ハンズオン リベンジ」として勉強会を開催しよう"と思ってたのですが、まだ知識が足りていないことと、仕事でサーバーリプレース作業をしていまして、これが来年6月までに月2,3の土曜出勤(日曜日は予備日)となり実施日も2週間前くらいでないと確定しないので、延び延びになっています。
自分的は絶対やりたいので来年のいつぞやまでお待ちください。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away