Rust の regex クレート を使うと、正規表現を使った様々な文字列処理を行うことができます。
Rust (Cargo) プロジェクト内で以下のように実行して Cargo.toml
に依存関係を追加すれば regex
の使用準備は完了です。
$ cargo add regex
パターンに一致するか調べる (is_match)
Regex#is_match メソッドを使うと、引数で渡した文字列に、Regex
のパターンに一致する部分文字列が含まれているかを調べることができます。
use regex::Regex;
let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
let input = "Today's date is 2023-01-07.";
if re.is_match(input) {
println!("日付らしき文字列が見つかりました");
}
Regex#is_match
メソッドは、パターンに一致する文字列が部分的にでも見つかれば true
を返します。
文字列全体がパターンに一致するかどうかを調べたい場合は、パターンに ^
(行頭)と $
(行末)を含めて、r"^\d{4}-\d{2}-\d{2}$"
のようにします。
パターンに一致した位置を調べる (find, find_iter)
Regex#find メソッドは、パターンに一致する部分文字列が見つかったときに regex::Match オブジェクトを返します。
見つからない場合は Option::None
を返します。
Match
のメソッドを使って、実際に一致した部分文字列や、その位置を取得できます。
Regex#find
は最初に見つかった部分文字列だけを返しますが、複数回マッチさせたい場合は、代わりに Regex#find_iter メソッドで regex::Matches オブジェクトを取得します。
Matches
は Iterator
を実装しているので、ループ処理が可能です。
let re = Regex::new(r"\d+").unwrap();
let input = "server: ok=100 changed=50 unreachable=0 failed=3";
for m in re.find_iter(input) {
println!("Found `{}` at {}-{}", m.as_str(), m.start(), m.end());
}
グルーピングして部分文字列を抽出する (captures, captures_iter)
Regex#captures メソッドは、パターン中の括弧 (()
) でグルーピングされた部分を一度に抽出して、regex::Captures オブジェクトを返します。
Captures
は Vec
と同様にアクセス([]
や get
)することができ、インデックス 0 には、パターンに一致した文字列全体が格納されています。
let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
let input = "Eiichi Shibusawa was born on 1840-02-13 and died on 1931-11-11.";
match re.captures(input) {
Some(caps) => {
println!("年月日: {}", &caps[0]);
println!("年: {}", &caps[1]);
println!("月: {}", &caps[2]);
println!("日: {}", &caps[3]);
}
None => println!("Not found"),
}
複数回マッチさせたいときは、captures
の代わりに captures_iter を使用します。
for caps in re.captures_iter(input) {
println!("年: {}, 月: {}, 日: {}", &caps[1], &caps[2], &caps[3]);
}
正規表現パターンの中で、キャプチャグループに名前を付けるには (?P<name>exp)
というシンタックスを使用します。
let re = Regex::new(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})").unwrap();
let input = "Eiichi Shibusawa was born on 1840-02-13 and died on 1931-11-11.";
for caps in re.captures_iter(input) {
println!(
"年: {}, 月: {}, 日: {}",
&caps["year"], &caps["month"], &caps["day"]
);
}
パターンに一致する部分を置換する (replace, replace_all)
Regex#replace メソッドを使用すると、正規表現パターンに一致した部分を任意の文字列に置換できます。 最初に一致した部分だけでなく、一致した部分をすべて置換したいときは、Regex#replace_all メソッドを使用します。
let re = Regex::new(r"[m|M]aku").unwrap();
let input = "I am maku. You are not Maku.";
let output = re.replace_all(input, "####");
println!("{}", output); //=> "I am ####. Your are not ####."
パターンの中で括弧 (()
) を使ってキャプチャグループを構成しておけば、実際に一致した部分文字列を、置換文字列の中で $1
や $2
で参照できます。