match式

match 式は、値のパターンマッチによって処理を分岐する構文(式)だ。

基本的な使い方

まずはいちばん基本的な、switch 文のような使い方。

scala> val name = "Taro"
name: String = Taro

scala> name match {
| case "Taro" => "male"
| case "Jiro" => "male"
| case "Hanako" => "female"
| }
res0: String = male

変数 name の値によって分岐している。キーワード match を対象となる変数の後に書くのが特徴的だな。res0 とあるように、match 式も値を返す。

match の対象には String 型じゃなく、ほかの型も使える。

scala> val n = 5
n: Int = 5

scala> n match {
| case 1 => "one"
| case 2 => "two"
| case 3 => "three"
| case _ => "many"
| }
res1: String = many

最後の case の _ は、ワイルドカードパターンといって、どんな値にもマッチする。Scala では分岐の漏れを防ぐためによく使われるようだ。

パターンをまとめる

複数のパターンで同じ処理をしたいときには、| で区切ってパターンを並べることでまとめることができる。こんなふうに。

scala> "def" match {
| case "abc" | "def" =>
| println("first")
| println("second")
| case "ghi" =>
| println("third")
| }
first
second

ここで気が付いたけど、分岐先が複数の式になってても { } で囲う必要はないんだな。

パターンマッチによる値の取り出し

パターンに一種の変数を使うことで、対応する値を取り出すことができる。

scala> val lst = List("A", "B", "C")
lst: List[String] = List(A, B, C)

scala> lst match {
| case List("A", b, c) =>
| println("b = " + b)
| println("c = " + c)
| case _ =>
| println("nothing")
| }
b = B
c = C

この例では、先頭が “A” であるような3要素のリストにマッチし、2番目と3番目の要素がそれぞれ b と c に代入されている。

ガード式

パターンにガード式をつけることで、条件を加えることができる。たとえば、「先頭が “A” のリストで、かつ、2番目が “B” でない」というパターンは次のように書ける。

scala> lst match {
| case List("A", b, c) if b != "B" =>
| println("b = " + b)
| println("c = " + c)
| case _ =>
| println("nothing")
| }
nothing

この例では、「先頭が “A” のリスト」にはマッチするけど「if b != “B”」が偽になるので最初のパターンにはマッチせず、あとのワイルドカードパターンにマッチして nothing が返ってきている。

asパターン

パターンの前に変数名と @ をつけることで、パターンにマッチした値を変数に束縛(「束縛」って用語を使ってるな)することができる。これは後からパターンの値を参照するのに便利。

scala> val lst2 = List(List("A"), List("B", "C"))
lst2: List[List[String]] = List(List(A), List(B, C))

scala> lst2 match {
| case List(a@List("A"), x) =>
| println(a)
| println(x)
| case _ =>
| println("nothing")
| }
List(A)
List(B, C)

ここでは、List(“A”) というパターンの値を変数 a に束縛して後から使っている。

というところで、とりあえずはここまで。

MediaWikiのバックアップ

先日、データのバックアップサーバを作ったので、MediaWiki で運用している wiki のバックアップもすることにした。

MediaWiki でバックアップが必要なのはつぎの2つ。

  • /var/www/html/wiki 以下のファイル群
  • データベース

ファイル群は単純に rsync でバックアップする。データベースは mysqldump コマンドでファイルに書きだしたあと、gzip で圧縮してから rsync でバックアップする。

こんなスクリプトにした。

mysqldump -hlocalhost -uxxxx -pyyyy wiki | gzip > wiki.sql.gz
rsync -av -e "ssh -i ~/.ssh/synckey" --delete /home/takatoh/wiki.sql.gz takatoh@nightschool:/mnt/pikaia/backup/wiki/db
rsync -azv -e "ssh -i ~/.ssh/synckey" --delete /var/www/html/wiki/ takatoh@nightschool:/mnt/pikaia/backup/wiki/wiki

xxxx はデータベースのユーザー名、yyyy はパスワード、wiki がデータベース名だ。

これで試してみたら OK だったので、cron に登録して毎日バックアップすることにした。