正規表現

Rustの正規表現は言語仕様には含まれていないようだが、Regexクレートがあるので問題なく正規表現が使える。正規表現パターンもマッチさせる文字列もUnicodeが使える。

Regexを使うには、Cargo.tomlに依存関係を追加する。

[dependencies]
regex = "1"
  1. パターンにマッチするか否か
  2. キャプチャ
  3. 置換
  4. 大文字小文字を区別しない
パターンにマッチするか否か

単純に文字列がパターンにマッチするかどうかなら、is_match()を使う。src/main.rsに以下のコードを書く。正規表現の"^"は行の先頭にマッチすることを表すので、"^こんにちは"なら先頭が"こんにちは"である文字列にマッチする。

use regex::Regex;

fn main() {
    let s = "こんにちは、世界!";
    // 先頭が"こんにちは"で始まっているか
    let re = Regex::new(r"^こんにちは").unwrap();
    println!("{}", re.is_match(s));
}
true

残念ながら後方参照はサポートされていないようだ。後方参照とは、正規表現の中でr"(モチ|ふわ)\1"のように、左方のキャプチャをパターン内で参照(\N)することを言う。例えば、"モチモチ"、"ふわふわ"にはマッチさせたいが、"モチふわ"にはマッチさせたくない場合に(この程度であれば素直に書けば良いだけだが)便利だ。

regex parse error:
    (モチ|ふわ)\1
           ^^
error: backreferences are not supported
キャプチャ

また、文字列から特定のパターンをキャプチャするには、captures()を使う。例えば、日付を表す文字列から年、月、及び日を抽出する。正規表現の"\d"は数字1字を表し、"{4}"は直前の文字の繰り返し数を表す。つまり、"\d{4}"なら数字4桁という事になる。

"()"はキャプチャする部分正規表現を表し、以下では西暦4桁、月2桁、及び日2桁の3つの文字列をそれぞれ&caps[1]、&caps[2]、及び&caps[3]といった形で取り出すことができる。因みに、&caps[0]はパターンにマッチした文字列全体である。

use regex::Regex;

fn main() {
    let s = "2021年01月08日";
    // 西暦、月、及び日をそれぞれ抽出する
    let re = Regex::new(r"^(\d{4})年(\d{2})月(\d{2})日$").unwrap();
    let caps = re.captures(s).unwrap();
    println!("{}-{}-{}", &caps[1], &caps[2], &caps[3]);
}
2021-01-08
置換

replace()を使えば文字列の置換も可能だ。以下は正規表現を使い、"極めて高速"、"非常に高速"、または"超高速"の3種の文字列を"爆速!"に置換する。(実際にRustが爆速なのかどうかは確認していない。)

"|"はorを表し、()内が"極めて"、"非常に"、または"超"のどれでも良い。

use regex::Regex;

fn main() {
    let s = "Rustは非常に高速です。";
    // "極めて高速"、"非常に高速"、または"超高速"を"爆速!"に置換
    let re = Regex::new(r"(極めて|非常に|超)高速").unwrap();
    let result = re.replace(s, "爆速!");
    println!("{}", result);
}
Rustは爆速!です。

置換においては、置き換える文字列中でキャプチャした結果を$Nで参照できるので、先ほどの日付の例はより簡潔に書くことができる。

use regex::Regex;

fn main() {
    let s = "2021年01月08日";
    // 日付を置換
    let re = Regex::new(r"^(\d{4})年(\d{2})月(\d{2})日$").unwrap();
    let result = re.replace(s, "$1-$2-$3");
    println!("{}", result);
}
2021-01-08
大文字小文字を区別しない

Regexは、通常は大文字小文字を区別する(case-sensitive)ので、大文字小文字を区別せず(case-insensitive)に文字列をパターンにマッチさせるには、"(?i)"フラグを正規表現に付加する。以下は大文字小文字を区別せずに文字列を"rust"にマッチさせる例である。

use regex::Regex;

fn main() {
    let s = "Hello, Rust!";
    // 大文字小文字を区別せずにマッチさせる
    let re = Regex::new(r"(?i)rust").unwrap();
    println!("{}", re.is_match(s));
}
true
(2021/01/08)

新着情報
【オープンソースソフトウェア環境構築】Apple silicon Macで開発環境を構築
【Rust Tips】Actix webでJSONをPOSTする
【Rust Tips】コマンドライン引数を取得する

Copyright© 2004-2021 モバイル開発系(K) All rights reserved.
[Home]