正規表現:見た目ほど怖くない
正規表現は読めないという評判があります。そうである必要はありません。
ドキュメント内のすべてのメールアドレスを見つける必要があります。あるいは電話番号を検証。あるいは乱雑なテキストから日付を抽出。
誰かが「regexを使え」と言います。構文をググり、^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$ のようなものを見つけ、即座にタブを閉じます。
正規表現が威圧的に見えるのは、人々が明確さではなく賢さを示すために書くからです。それを修正しましょう。
リテラルマッチングから始める
Regexはパターンを見つけます。最もシンプルなパターンはリテラルテキスト。
cat は「The cat sat.」の中の「cat」にマッチ。何も派手じゃない。
http はあらゆるURLの中の「http」にマッチ。まだ単純。
徐々にワイルドカードを追加
. は任意の1文字にマッチ。c.t は「cat」、「cot」、「cut」にマッチ。
* は「前のものが0回以上」を意味。ca*t は「ct」、「cat」、「caat」、「caaaaaat」にマッチ。
+ は「1回以上」を意味。ca+t は「cat」と「caat」にマッチしますが、「ct」にはマッチしません。
? は「0回または1回」を意味。colou?r は「color」と「colour」の両方にマッチ。
文字クラスはあなたの友達
[aeiou] は任意の母音にマッチ。[0-9] は任意の数字にマッチ。[A-Za-z] は任意の文字にマッチ。
\d は [0-9] の短縮形。\w は単語文字(文字、数字、アンダースコア)にマッチ。\s は空白にマッチ。
これらの構成要素がほとんどの実世界のパターンを扱います。
アンカーが位置をコントロール
^ は「行の開始」を意味。$ は「行の終端」を意味。
^Hello は「Hello world」にマッチしますが、「Say Hello」にはマッチしません。
world$ は「Hello world」にマッチしますが、「world peace」にはマッチしません。
グループが部分をキャプチャ
括弧はものをグループ化します。後で使うためにキャプチャもします。
(\d{3})-(\d{4}) は「555-1234」にマッチし、「555」と「1234」を別々にキャプチャ。
これがパターンマッチから特定のデータを抽出する方法です。
実例、解説付き
メール(簡略版):
[\w.-]+@[\w.-]+\.\w+
翻訳:単語文字/ドット/ハイフン、それから@、それからまた同じ、それからドット、それから単語文字。
電話番号:
\d{3}[-.\s]?\d{3}[-.\s]?\d{4}
翻訳:3桁、オプショナルのセパレーター、3桁、オプショナルのセパレーター、4桁。「555-123-4567」、「555.123.4567」、「5551234567」にマッチ。
日付(MM/DD/YYYY):
\d{2}/\d{2}/\d{4}
翻訳:2桁、スラッシュ、2桁、スラッシュ、4桁。
よくある間違い
特殊文字のエスケープを忘れる。 . はregexで「任意の文字」を意味します。リテラルのドットにマッチするには、\. を使いましょう。
貪欲すぎる。 .* は可能な限り多くマッチします。HTMLタグで、<.*> を <b>bold</b> に適用すると全体にマッチし、<b> だけではありません。非貪欲マッチには <.*?> を使いましょう。
複雑にしすぎ。 本物のメール検証が必要なら、ライブラリを使いましょう。「正しい」メールregexは数百文字の長さです。
Regexを使うべきでない時
HTMLやJSONのパース。適切なパーサーを使いましょう。
複雑な検証ロジック。コードは多くの場合、1つの巨大なパターンより明確です。
文字列メソッドが機能する時。"hello".startsWith("he") は /^he/ より明確。
Regexはツールです。あらゆるツール同様、特定の仕事には良く、他には不格好。シンプルに始め、作りながらテストし、賢くあろうとしない。読めるregexが印象的なregexより良いです。