[JavaScript] 正規表現でデータを操る
〜基礎知識編〜
今回は正規表現の基本について触れてみようと思います。
プログラムを組まない方には馴染みの無い言葉だと思いますが、ネットで調べると「文字列の集合を一つの文字列で表現する方法の一つ」とか「文字列の特徴と特殊記号の組み合わせであらわしたもの」と出ます。ちょっと言っていることがよく解らないですよね…。
自分の言葉で簡単に言えば「文字データから指定した条件に一致した文字列を検索するときに使うもの」でしょうか。ただ、その書き方は単純なものから複雑なものまで幅広く、突き詰めるとあのオライリー社が「正規表現」という分厚い本を出版するくらい奥は深いです。著者によると、
正規表現を使えば、データを自由に操れるようになる。データをコントロールし、自分のための仕事をさせられるのである。正規表現をマスターすることは、自分のデータを支配することなのだ。
とあります。「データを支配する」カッコイイですね。
JavaScriptをある程度使いこなしてはいるけど、正規表現は何となく避けてきた人って結構多いのではないでしょうか?これを機に少し理解を深めていきましょう。
ただ、基本的なことを全てここには書けないので、一つの例を元に紐解きます。
さて本題ですが、正規表現は身近なところですと、画像にマウスを載せるとファイル名末尾に「_off」とついた画像を「_on」がついた画像に切り替えるJavaScriptの命令に使うことができます。
$("img.rollover").mouseover(function(){ $(this).attr("src",$(this).attr("src").replace(/^(.+)_off(\.[a-z]+)$/,"$1_on$2")); }).mouseout(function(){ $(this).attr("src",$(this).attr("src").replace(/^(.+)_on(\.[a-z]+)$/,"$1_off$2")); });
このソースで言うと、下記が正規表現の記述です。完全に暗号ですね。
/^(.+)_off(\.[a-z]+)$/
まず、いきなりですが、上記の正規表現がどういう文字列の検索条件を表しているのかを言葉に置き換えてみると、
先頭に何でもいい1つ以上の連続した文字 + 「_off」という文字 + 終端に「.」という文字と1つ以上の連続した小文字アルファベットということになります。
※「」は中の文字のみを指します
つまり下記の様な文字列を検索することができます。
a_off.jpg
1_off.gif
bbb_off.b
hogehoge_off.hogee
等など。
これを一つずつ紐解いてみます。
1.各記号の意味
正規表現には下記の様な1文字(1組)で意味を持つ「メタ文字」と呼ばれる記号があります。
^ $ . + * ? | [] ()
【^】文字列の最初ということを表す
例:^こんにちは(検索結果:こんにちは こんにちは。お昼のニュースです 等)
検索したい文字の前に【^】を付けることで、先頭に【こんにちは】のつく文字列を取り出します。
【$】文字列の最後ということを表す
例:さようなら$(検索結果:さようなら また明日ね。さようなら 等)
検索したい文字の後ろに【$】を付けることで、終端に【さようなら】のつく文字列を取り出します。
【 . 】何でもいい一文字を表す
例1:私は.です(検索結果:私は男です 私は女です 等)
例2:私は..です(検索結果:私は生徒です 私は先生です 等)
何か1文字入る記号と覚えればいいと思います。連続で複数書くことができ、文字数を指定することができます。
【+】直前の文字が1文字以上連続することを表す
例:あれ+ー(検索結果:あれー あれれれー 等)
【+】の直前の【れ】が1文字以上連続する文字列を取り出します。
【*】直前の文字が0文字以上連続することを表す
例:あら*ー(検索結果:あー あらー あらららー 等)
【*】の直前の【ら】が0文字以上連続する文字列を検索します。【+】との違いは、0文字以上が対象なので、その文字が無い場合も取り出します。
【?】直前の文字が1つあるか、もしくは無いことを表す
例:Windows ?10(検索結果:Windows 10 Windows10)
【?】の直前の文字がある場合と無い場合を取り出します。上記のようなスペースがあったりなかったりするケース両方を取り出す場合等に便利です。
【|】いずれかの文字列を表す
例:りんご|みかん|バナナ|スイカ(検索結果:りんご みかん バナナ スイカ)
or検索のようなもので、どれかが当てはまれば取り出されます。
【[ ]】括弧の中の文字どれかを表す
例:今日は[晴雨曇]です(検索結果:今日は晴です 今日は雨です 今日は曇です)
アルファベットや数字全てを表したい場合、もちろんすべてを【[ ]】の中に書いてもいいのですが、下記の様に省略することができます。
小文字アルファベットなら【[a-z]】(大文字であれば【[A-Z]】)、数字なら【[0-9]】と表すことができます。続けて書くことも可能ですので【[a-z0-9]】と書けば、小文字アルファベット何か1文字と数字の何か1文字という組み合わせが取り出されます。
また、先ほど出てきた【^】ですが、【[ ]】の中にある場合は否定の意味に変化します。
【[^a-z]】であれば小文字アルファベット以外を指します。
そしてもう一つ注意しなければならない点があります。先程の【[^a-z]】では【^】は否定の意味のメタ文字として認識されますが、【[a-z^]】のように2文字目以降に使われる場合は通常の文字として扱われます。
【( )】グループ化
例1:(じゃ)+ーん(検索結果:じゃーん じゃじゃーん じゃじゃじゃーん)
例2:私は(りんご|みかん)が好き (検索結果:私はりんごが好き 私はみかんが好き)
例のように、【+】【*】【?】等を使う際には複数の文字を一つとしてまとめることができ、
【|】を使う場合は他の命令と組み合わせるために独立させることができます。そして、【( )】内の命令は優先して処理されます。数学と一緒ですね。
【\】メタ文字を通常の文字として使いたい場合に使用
例:\^
この文字自体はメタ文字ではなくエスケープ文字という扱いになります。メタ文字の【^】の前に【\】を付けることで【^】を通常の文字として扱えます。
【\】を文字として使いたい場合は【\\】と書きます。
2.正規表現という指定
正規表現は色々な言語に使われますが、プログラム言語によって使う際のルールが異なります。
JavaScriptの場合「/」で囲ったところが正規表現として扱われます。
/^(.+)_off(\.[a-z]+)$/
3.細分化して確認してみる
このままだとどこで区切れるのかが分かり辛いので色分けをして細分化してみます。
上記の「1.各記号の意味」をよく読めば、細分化されたもの一つ一つの意味は分かると思います。
/^(.+)_off(\.[a-z]+)$/
^(.+)
先頭に何でもいい1つ以上の連続した文字
_off
「_off」という文字
(\.[a-z]+)$
終端に「.」という文字 + 1つ以上の連続した小文字アルファベット
繋げてみてみると、最初に紹介したように
先頭に何でもいい1つ以上の連続した文字 + 「_off」という文字 + 終端に「.」という文字と1つ以上の連続した小文字アルファベットを取り出す正規表現ということになります。
簡単に言えば「●●●_off.●●●」という画像ファイル名を検索したいという命令だったわけですが、一つ一つ追っていけば意味が分かると思います。
まとめ
いかがだったでしょうか。
まだ説明できてないことはたくさんありますが、スクリプトを書く人だけでなくHTMLの一括置換をする際にも役立つ場合があり、知っておいて絶対に損はないので、興味のある方は下記のサイトを参考にしてみてください。
こんな時にすごく使える!という事例や、正規表現の基本などがわかるサイト、正規表現を実際にシミュレーションできるサイトを載せておきます。
・【業務効率が変わる!】こんな時に役に立つ「正規表現」の使い所
・サルにもわかる正規表現入門
・正規表現シミュレータ
WEBプログラマー / O.K