結論
- 正規表現ができれば力づくでなんとかできることが増える!?
- 全部は理解しなくても、まずは使えるものだけ使ってみよう!
- 便利すぎてきっと嫌悪感よりコスパが勝つと思います
「. ^ $ [ ] * + ? |」について
参考
サルにもわかる正規表現入門
https://userweb.mnet.ne.jp/nakama/
合わせて読みたい読んでほしい記事
なんでもいいひと文字
使い勝手のとてもいいやつです。個人的に多用しすぎる傾向が…。そうしていると正規表現が上達しません悲笑。
「.ドット」
行頭^、行末$
^おは
です$
^おはです$
「おなじ文字」の繰り返し
3つあります。それぞれ上手に使い分けましょう。表を作ってみました。あってるかな?
* + ?
これら3つの記号は直前の文字に作用します。
0 | 1 | 2以上 | |
---|---|---|---|
* | 〇 | 〇 | 〇 |
+ | – | 〇 | 〇 |
? | 〇 | 〇 | – |
この表が書けるといいですね!
ちなみに「?」について。「?」から連想できる「true、false」。よって、0か1かを想起できるとよい。
「*」
なるほど、いつも何も考えずに「.*」使っていたから「おなじ文字」という言葉が新鮮なんだな。
- 正規表現の「*」とワイルドカードの*は混乱する。
- よくWindowsのファイル検索で「とにかく何でもあれー(by三四郎)」の時に使ったりするワイルドカード「*」
- ワイルドカードの「*」は何でも来いの「*」です。粗削りしたいときに便利ですよね。
- 「*」は「直前の文字」が関わってきます。
- パターンは3パターンしかないみたいです。
引用します。
RegEx(正規表現):「おー*い」
以下のパターンが当てはまります。
おい
おーーい
おーーーーい
ワイルドカード脳だと1番目が意外ですね。というか全部ですね。ワイルドカードなら「おなじ文字」じゃなくてもいいので。
ワイルドカードを表現したいなら「お.*い」ということでしょうか?あってますかね?
「*は直前の文字が無いのも当てはまる、1個あるのも当てはまる。同じ文字が続くのも当てはまる。」ということでしょうか?
間違っていなければ、自分の頭に入りやすい言葉に書き直したほうがいいかもしれません。
ここから混乱し始めます。
「+」
RegEx(正規表現)「おー+い」は、「ー」がひとつは絶対必要です。あとは*と同じ。
「*、+」と続き、次は「?」です。
さらに混乱。スペック低いな私。
「?」
Regex:Windows?
ズバリ次の2つを表現します
Windows
Window
こんなのどうでしょう?
「直前の文字がtrueかflaseか。」
直前の文字があるかないかだけ。繰り返しっていうのは無くなりました。少し安心(ラク)しました。
しかし、3つの記号(メタ文字)が出てきたので、どれが何か混ざってしまうと意味がありません。
「?」はこんな使い方もできます。
例:半角スペースある?
検索したい「TCPIP」
でもデータベースには入力者によって「TCP IP」や「TCPIP」かもしれない。
だから「取りこぼしが無いように正規表現」を使う(?)
Regex「TCP ?IP」
これでどっちも検索できます!
これいまは探す対象が2つですけど、
膨大なデータ、文字列から見つけ出すにはめっちゃラクなんですよ!
だから、正規表現は記号だらけでほんとは嫌悪感アリアリなんですが、最低限覚えることが少なくて、その割には超強力なんで嫌悪感と便利を天秤にかけると「使えるスキル」と認定しました。(「便利」はどこへ行った笑?)
改めて「*, +, ?」について
直前の文字が、ない、1個ある、1個以上ある、このどれかに当てはまるということでしょうか?
Rubyのある構文・メソッドの引数表に似てますね。0か1かそれ以外みたいな。
再度、表を表示します。
0 | 1 | 2以上 | |
---|---|---|---|
* | 〇 | 〇 | 〇 |
+ | – | 〇 | 〇 |
? | 〇 | 〇 | – |
これまで学んだものをコラボしてみましょう!
「.*」
文字がないか、なんでもいい文字が続くこと。
ワイルドカードと同じ意味。「無くてもいいし、なにがあってもいい」ということですね。
正規表現ムズ!
どこまでを表現する?「.*」
これはワイルドカードと同じ意味ということですが、どこまで続くのでしょうね?と言っても「どこまで続く」という意味がわからないと思います。私も半分わかっていません。
String「ワイルドカード」
Regex「ワ.*ド」
ワイルドカード?ワイルド?どっちも当てはまる?
どれが抽出される? => (答えは「ワイルドカード」です。)
表現が正しいかわかりませんが、正規表現は基本欲張りなので取れるだけ取ります!
これはイメージですが「ワイルド」でいったん止まっても、正規表現君は「ん?まだあるぞ!」ということで「ワイルドカード」全部を取りにいきます。
「最短マッチ」
欲張りを止めるために「?」を使います。これ結構重要です。
読み解くと(私は)混乱するので丸暗記してます。「最短マッチ」と言うらしいです。
下記のコードはRubyです。
str = "ワイルドカード"
puts str.slice(/ワ.*ド/)
puts str.slice(/ワ.*?ド/) #「?」を付けると最初のマッチで終了します。
atr = "ワイルドカードマイルド"
puts atr.slice(/ワ.*ド/) #最後まで取りにいきます
btr = "ワイルドカードマイルド"
puts atr.slice(/ワ.*?ド/) #ワイルドで止まります。
混乱する…。最短マッチって…。
Rubyの文字列処理で正規表現は結構使えて便利なのでゆっくり使っていきましょう!
「|」いずれかに当てはまればOK
引用です。
Strin::"IBM マイクロソフト Apple ネットスケープ"
Regex:IBM|マイクロソフト|Apple|ネットスケープ
Rubyの検索コード
str = "IBM マイクロソフト Apple ネットスケープ"
puts str.slice(/IBM|マイクロソフト|Apple|ネットスケープ/)
#sliceメソッドの仕様上、最初のマッチだけです。
puts str.scan(/IBM|マイクロソフト|Apple|ネットスケープ/)
#マッチするものを全部検索してくれて配列で返してくれます。
「[]」
「 [ ] で括られた中の文字は、その中のどれか1つに合致する」です。
この[]の中の表現方法は多岐にわたります。
[]は1文字を表現します。
A[ABCDEFG]B
A[A-Z]B
A[012345]B
A[0-9]B
いずれかも全体で3文字の文字列です。
ちなみに[]の中がなんでもいいなら…一番最初にやりましたね![]は使わず「.ドット」のみでOKです。
「以外」という選択肢。
「^」を使います。行頭という意味ではありません。[]の中で使うと反転、または除外、以外として使えます。
A[^A]Bは「A」以外のすべての文字が入ります。とにかくAだけは嫌なんですね。
A[^A0-9]BはAと数字以外を表現します。^が後ろまで適応されるのがポイントですね。
ちなみに「^」は一番最初じゃないと意味を持ちません。2番目以降に書くと普通の「^」です。
「JIS漢字コード表」ってのがあるらしい。
[か-こ]は「が行」も候補になります。
Rubyコード
str = "グアテマラ"
p str.match?(/[カ-コ]/)
#=>ture
str = "ぐあてまら"
p str.match?(/[か-こ]/)
#=>true
str = "ぐあてまら"
p str.match?(/[カ-コ]/)
#=>false
[]の中ではエスケープは必要ありません。
.や*が普通の文字として認識されます。
引用
[[567]
#=>4つの文字
[\]567]
#=>閉じないようにエスケープ必要
[\\PR]
#=>これも特別文字なのでエスケープ
[-4]
#=>これは2文字
[4-]
#=>これはダメ
覚えることいっぱいあるね…。ゆっくりでいいし、使えるものを積極的に使おう!
正規表現は文字列にして文字列にあらず。(?)
それは正規表現検索?それとも文字列検索?
ここまで正規表現を学んできましたが、検索したい文字列が1パターンと確定しているなら正規表現を使用するまでもなく文字列で”マイクロソフト”と決め打って良いです!
ということで「欲しいものが複数パターン考えられる」ときは正規表現の出番ということですね!(自信ない…)
- 検索キーワードがひとつ→文字列直接検索
- 検索キーワードが複数のパターン→正規表現パターンマッチ
考え方によっては正規表現を使わずに済みます。
例えば。
- 探したいキーワードが3パターンある。
- 文字列検索を3回かける。
これでいいですね。
正規表現、使えたら出来る人っぽいと思います。シンプルに効率がいいです。もし検索パターンが50個あって、正規表現で1行で済むなら誰が見ても効率的ですよね!