文字列パターンの操作

はじめに

Mathematica の一般的な記号文字列パターンを使って,強力な文字列操作を効率よく行うことができる.このドキュメントは,文字列パターンの詳細について,使用法と実装に関するノートを含めて説明するものであり,ヘルプシステム他の箇所では扱われていない点を特に詳述する.

Mathematica の中心にあるのは通常の式でパターンを記述する強力な言語である.この言語は関数の定義,置換,検索,のようなコンストラクト等に使われている.
In[1]:=
Click for copyable input
Out[1]=
In[2]:=
Click for copyable input
Out[2]=
In[3]:=
Click for copyable input
Out[3]=
Mathematica の文字列パターンは,同じコンストラクトを使ってテキスト文字列中のパターンを記述する.文字列を文字が連続するものと考えて,一般的な Mathematica パターンの原則を適用することができる.さらに,文字列特有のパターンコンストラクトもいくつかある.
In[4]:=
Click for copyable input
Out[4]=
In[5]:=
Click for copyable input
Out[5]=
In[6]:=
Click for copyable input
Out[6]=
文字列パターンを指定する別の方法として,正規表現を使うこともできる.この方がよりコンパクトになることが多いが,読みにくい.
In[7]:=
Click for copyable input
Out[7]=
In[8]:=
Click for copyable input
Out[8]=
In[9]:=
Click for copyable input
Out[9]=

次は文字列パターンを認識するいくつかの関数である.

StringMatchQ["s",patt]spatt にマッチするかどうか判定する
StringFreeQ["s",patt]spatt にマッチする文字列が含まれていないかどうか判定する
StringCases["s",patt]patt 中の s の部分文字列のリストを与える
StringCases["s",lhs->rhs]lhsrhs で置き換える
StringPosition["s",patt]patt にマッチする部分文字列の位置のリストを与える
StringCount["s",patt]いくつの部分文字列が patt にマッチするか数える
StringReplace["s",lhs->rhs]lhs にマッチするすべての部分文字列を置き換える
StringReplaceList["s",lhs->rhs]lhs を置換するすべての方法をリストする
StringSplit["s",patt]patt にマッチするすべての部分文字列のところで s を分割する
StringSplit["s",lhs->rhs]lhs で分割し rhs を挿入する

文字列パターンをサポートする関数

一般的な文字列パターン

一般的な文字列パターンは,Mathematica のパターンオブジェクトに類似のパターンオブジェクトによって形成される.複数のパターンオブジェクトの結合にはStringExpression演算子を用いる.
In[10]:=
Click for copyable input
Out[10]//FullForm=
StringExpressionStringJoinと非常に似ている.異なる点は前者は文字列ではないものも許容し,リストを平坦化しない点である.純粋な文字列の場合,両者は等しい.
In[11]:=
Click for copyable input
Out[11]=

文字列で使うことができるオブジェクトのリストは,通常の Mathematica パターンのリストとほぼ一致する.文字列パターンに関しては,文字列は一連の文字とみなされる.すなわち,は,通常のパターンコンストラクトが適用できるString[a, b, c]のようなものとみなされる.

次のオブジェクトは記号的な文字列パターンで使える.

"string"文字列
_単一の文字
__1つまたは複数の文字の入った部分文字列
___文字が入ったまたは入らない部分文字列
x_,x__,x___x という名の部分文字列
x:patternx という名のパターン
pattern..1回あるいは複数回繰り返されたパターン
pattern...繰り返されたあるいは繰り返されなかったパターン
{patt1,patt2,...}またはpatt1|patt2|... の少なくとも1つにマッチするパターン
patt/;condcond を評価するとTrueになるパターン
pattern?test各文字について testTrueを返すパターン
Whitespace空白類文字の文字列
NumberString数の文字
DatePattern[spec]日付の文字列
charobj文字のクラスを繰り返すオブジェクト(以下参照)
RegularExpression["regexp"]正規表現にマッチする部分文字列
StringExpression[...]任意の文字列式

次は,文字クラスを表す

{c1,c2,...}のいずれか
Characters["c1c2..."]のいずれか
CharacterRange["c1","c2"]から
HexadecimalCharacter16進数字0-9,a-f,A-F
DigitCharacter0から9までの数字
LetterCharacter文字
WhitespaceCharacterスペース,改行,タブ,その他の空白類文字
WordCharacter文字または数字
Except[p]p に一致するもの以外の任意の文字

次は,文字列中の位置を表す

StartOfString文字列全体の先頭
EndOfString文字列全体の末尾
StartOfLine行頭
EndOfLine行末
WordBoundary文字記号とその他の境界
Except[WordBoundary]文字の境界以外の任意の場所

以下は複数の可能性がある場合にどのマッチを取るかを決める

Shortest[p]p にマッチする最短のもの
Longest[p]p にマッチする最長のもの(デフォルト)

以下はこれらのオブジェクトに関する重要な問題である.

のワイルドカードは,改行を含むどの文字にもマッチする.改行以外のすべての文字にマッチするようにするのには(正規表現の"."のように),Except["\n"]Except["\n"]..Except["\n"]...を使う.
In[12]:=
Click for copyable input
Out[12]=
In[13]:=
Click for copyable input
Out[13]=
In[14]:=
Click for copyable input
Out[14]=
のようなパターンのリストは,のような代替物のリストと等価である.CharactersCharacterRangeのような関数を文字クラスの指定に使うことができるので,これは便利である.
In[15]:=
Click for copyable input
Out[15]=
Condition()が使われると,Mathematica の他の部分に関する限り,これに含まれるパターンは文字列として扱われる.このため,場合によってはToExpressionを使わなければならないことがある.
In[16]:=
Click for copyable input
Out[16]=
通常の Mathematica パターンと同様に,PatternTest()の関数も各文字それぞれに適用される.
In[17]:=
Click for copyable input
Out[17]=
WhitespaceコンストラクトはWhitespaceCharacter..と等価である.
In[18]:=
Click for copyable input
Out[18]=
通常の文字列パターンにRegularExpressionオブジェクトを挿入することができる.
In[19]:=
Click for copyable input
Out[19]=
これは,が前にある単語だけを拾ったことを確認するために,後読みの制約条件(「正規表現」参照)を挿入する.
In[20]:=
Click for copyable input
Out[20]=
StringExpressionオブジェクトはネストさせることができる.
In[21]:=
Click for copyable input
Out[21]=

文字列パターンのExceptコンストラクトは,単一の文字,あるいは単一の文字クラスを表す単一引数を取る.

次は,文字列から母音以外のすべての文字を削除する.
In[22]:=
Click for copyable input
Out[22]=
異なる長さのパターン(等)をマッチさせようとするときは,デフォルトで,可能な最長マッチがまず試される.最初に最短マッチを試させるのには,パターンの関連箇所をShortest[ ]で包み込む.
In[23]:=
Click for copyable input
Out[23]=
In[24]:=
Click for copyable input
Out[24]=
何らかの理由で最短マッチ中の最長マッチが必要な場合には,Longestを使うことができる.
In[25]:=
Click for copyable input
Out[25]=
In[26]:=
Click for copyable input
Out[26]=
Longestを使う代りにパターンを書き換えてもよい.
In[27]:=
Click for copyable input
Out[27]=

正規表現

正規表現のシンタックスは,その元になっているPCRE(Perl準拠正規表現)ライブラリに従っている.このライブラリはPerlのシンタックスにきわめて近い(詳細は[1]を参照のこと). Mathematica の正規表現は RegularExpressionという頭部で示される.

正規表現文字列で,次の基本要素が使える.

c文字通りの文字 c
.新規行以外の任意の文字
[c1c2...] 中の任意の文字
[c1-c2]から の範囲の任意の文字
[^c1c2...] 以外の任意の文字
p*繰り返されたあるいは繰り返されなかった p
p+繰り返された p
p?現れたあるいは現れなかった p
p{m,n}m 回から n 回繰り返された p
p*?,p+?,p??マッチする最短の文字列
p*+,p++,p?+プログレッシブマッチ
(p1p2...), , ...にマッチする文字列
p1|p2 あるいは にマッチする文字列

次は文字のクラスを表す

\\d0から9までの数字
\\D数字ではないもの
\\sスペース,改行,タブ,その他の空白類
\\S空白類文字ではないもの
\\w文字記号(文字,数字,あるいは
\\W非文字記号
[[:class:]]名前の付いたクラス中の記号
[^[:class:]]名前の付いたクラスには含まれない記号

次の名前付きクラスが使える:alnumalphaasciiblankcntrldigitgraphlowerprintpunctspaceupperwordxdigit

次は,文字列中の位置を表す.

^文字列(あるいは行)の先頭
$文字列(あるいは行)の末尾
\\A文字列の先頭
\\z文字列の末尾
\\Z文字列の末尾(はじめに改行文字を1字許す)
\\b語の区切り
\\B語の区切り以外の任意の場所

以下は,それに続くすべての正規表現要素にオプションを設定する

(?i)大文字小文字を等しいものとして扱う(大文字小文字の区別をしない)
(?m)が行の先頭と末尾に一致する(マルチラインモード)
(?s)を改行にマッチさせる
(?x)すべての空白文字類を無視しの間にあるものすべてをコメントとして扱う
(?-\#c)オプションを解除する

次は,先読み/後読みコンストラクトである.

(?=p)後続するテキストは p にマッチしなければならない
(?!p)後続するテキストは p にマッチしなければならない
(?<= p)先行しているテキストは p にマッチしなければならない
(?<!p)先行しているテキストは p にマッチしなければならない

以下は,正規表現を巡る問題に関する若干の考察である.

次は,長さが2から4の一連の単語文字を探す.
In[28]:=
Click for copyable input
Out[28]=
所有を表す量限定子を付けると,マッチャーによって可能な限り多くの文字が取り出され,1文字たりとも見逃されない.これは,たとえパターンの他の部分でそうするようになっていても変わらない.
In[29]:=
Click for copyable input
Out[29]=
In[30]:=
Click for copyable input
Out[30]=
In[31]:=
Click for copyable input
Out[31]=
は16進法の文字に対応する.
In[32]:=
Click for copyable input
Out[32]=

正規表現でエスケープしなければならない文字の完全リストである.例えば,文字通りのピリオドを書く際にはを使い,文字通りのバックスラッシュを書く場合にはを使う.

文字クラスの中でのエスケープされる文字の完全リストはである.

デフォルトにより,は,それぞれ文字列の先頭と末尾にマッチする.マルチラインモードでは,これらは行の先頭/末尾にマッチする.
In[33]:=
Click for copyable input
Out[33]=
In[34]:=
Click for copyable input
Out[34]=
マルチラインモードでは,文字列の先頭と末尾を表すのにを使うことができる.
In[35]:=
Click for copyable input
Out[35]=
読みやすくするために,限定子を使って正規表現に空白文字やコメントを入れることができる.
In[36]:=
Click for copyable input
Out[36]=
名前付きのサブパターンは,(subpatt)のように前後にカッコを置く.こうすると番号付きのサブパターンとなる.指定のサブパターンの番号は開きカッコを数え,カッコのはじめから始める.この場合,n 番目のサブパターンは\\n で参照することができる.規則の右辺ではを使うことができる.はマッチしたすべてのパターンを参照する.
In[37]:=
Click for copyable input
Out[37]=
In[38]:=
Click for copyable input
Out[38]=
このコンテキスト(左辺の頭部がRegularExpression)で文字通りのが必要な場合には,バックスラッシュを使ってこれをエスケープすることができる(例:).
In[39]:=
Click for copyable input
Out[39]=
このような状況下で,文字通りのシングルバックスラッシュに文字通りのが続いたものが必要なときは,多少手の込んだ方法を用いて,一時的に文字列を2つに分割する必要がある.
In[40]:=
Click for copyable input
Out[40]=
パターンの一部をグループ化する必要があるが,そのグループを番号付きの部分パターンには数えたくない場合には,コンストラクトを使うことができる.
In[41]:=
Click for copyable input
Out[41]=

先読みと後読みのパターンは,マッチの一部としてテキストを実際に含まずに,パターンがマッチしていることを確実にするために使われる.

以下は文字列に後続する単語を選び出す.
In[42]:=
Click for copyable input
Out[42]=
これは,文字列中のすべての偶数を拾い出し,パーシャル数を含むマッチを探し出す.
In[43]:=
Click for copyable input
Out[43]=
先読み/後読みを使うと,マッチの前/後が数字ではないことが確認できる(後読み判定は場合によっては余分になるので注意のこと).
In[44]:=
Click for copyable input
Out[44]=

RegularExpressionとStringExpression

一般的な記号文字列パターンで使われるパターンオブジェクトと正規表現で使われるそれとの間には,密接な対応関係がある.以下は正規表現で書かれたものと記号文字列パターンで書かれたものの例のリストである.

正規表現
一般的な文字列パターン
説明
"abc""abc"文字通りの文字列
"."Except["\n"]改行以外の任意の文字
"(?s)."_任意の文字
"(?s).+"__1つ以上の文字(最長マッチを行う)
"(?s).+?"Shortest[__]1つ以上の文字(最長マッチは行わない)
"(?s).*"___0以上の文字
".*"Except["\n"]...0以上の文字(改行以外)
"a?b""a"|""~~"b"0あるいは1個のの前にある(等)
"[abef]"Characters["abef"]のいずれかの文字
"[abef]+"Characters["abef"]..任意の数のの文字
"[a-f]"CharacterRange["a","f"]からまでの任意の文字
"[^abef]"Except[Characters["abef"]]以外の任意の文字
"ab|efg""ab"|"efg"文字列あるいはとのマッチ
"(ab|ef)gh"or"(?:ab|ef)gh"("ab"|"ef")~~"gh"あるいはが続くもの(
"\\s"WhitespaceCharacter任意の空白文字
"\\s+"Whitespace1つ以上の空白文字
"(a|b)\\1"x:"a"|"b"~~x_にマッチする
"\\d"DigitCharacter任意の数字
"\\D"Except[DigitCharacter]任意の非数字
"\\d+"DigitCharacter..1つ以上の数字
"\\w"WordCharacter|"_"任意の数字,文字列,あるいは記号
"[[:alpha:]]"LetterCharacter任意の文字
"[^[:alpha:]]"Except[LetterCharacter]任意の非文字
"^abf"or"\\Aabc"StartOfString~~"abf"文字列の先頭にある文字列
"(?m)^abf"StartOfLine~~"abf"行頭にある文字列
"wxz$"or"wxz\\z""wxz"~~EndOfString文字列の末尾にある文字列
"wxz\\Z""wxz"~~"\n"|""~~EndOfString文字列の末尾あるいは改行の前にある文字列

一般的な文字列パターンには使われるが,正規表現には使われないパターンオブジェクトには,マッチの間に一般的なMathematica コードにアクセスできる条件(),パターンテスト()等が含まれる.

一般的な文字列パターンでは直接使えない,正規表現の特別なコンストラクトもある.先読み/後読みや指定の長さの繰返し等がこれに当たる.これらはRegularExpressionオブジェクトを挿入することで,より大きな一般的文字列パターンに埋め込むことができる.

文字列操作関数

以下では,さまざまな文字列操作関数の特徴や細かい区別等について取り上げる(各関数の詳細はそれぞれのリファレンスページを参照のこと).

StringMatchQ

StringMatchQは,文字列全体が特定のパターンにマッチするかどうかを判定する.
In[45]:=
Click for copyable input
Out[45]=
In[46]:=
Click for copyable input
Out[46]=

(後読み互換性により)メタキャラクタのをワイルドカードとして含むことができる点で,StringMatchQは特別である.Shortest[___] (RegularExpression["(?s).*?"])に等しく,Except[CharacterRange["A", "Z"]] (RegularExpression["[^A-Z]"])に等しい.

ゆえに,次の3つのパターンは等価である.
In[47]:=
Click for copyable input
Out[47]=
In[48]:=
Click for copyable input
Out[48]=
In[49]:=
Click for copyable input
Out[49]=

ここでは可能なマッチを探しているだけなので,技術的にはShortestの見かけに違いがない点に注意のこと.

パターン中のサブパターンでマッチした文字列の一部分にアクセスする必要がある場合は.StringCasesを使用する.

StringMatchQには,多少の矛盾を許容しながらマッチを求めるSpellingCorrectionオプションがある.これは,単一の文字列のみからなるパターンにのみ使用することができる.
In[50]:=
Click for copyable input
Out[50]=

StringFreeQ

StringFreeQは,文字列にパターンにマッチする部分文字列が含まれるかどうかをチェックするのに使われる.マッチする部分文字列を抽出することはできない.抽出にはStringCasesを使う.
In[51]:=
Click for copyable input
Out[51]=
In[52]:=
Click for copyable input
Out[52]=

StringCases

StringCasesは,文字列中のパターンの生起を見付け,サブパターンを取り出し,結果を処理する一般的な目的関数である.

パターンに一致する部分文字列を求める.
In[53]:=
Click for copyable input
Out[53]=
マッチする部分文字列を拾う.
In[54]:=
Click for copyable input
Out[54]=
In[55]:=
Click for copyable input
Out[55]=
マッチの回数を制限する.
In[56]:=
Click for copyable input
Out[56]=
規則のリストを使うことができる.
In[57]:=
Click for copyable input
Out[57]=
多くの文字列を効率よく処理するために第1引数として文字列のリストを与えることもできる(「効果的なマッチングのヒント」の説明も参照のこと).
In[58]:=
Click for copyable input
Out[58]=
In[59]:=
Click for copyable input
Out[59]=

Overlapsオプション

StringCasesStringPositionStringCountOverlapsオプションは,マッチを見付けた後のマッチャーの進め方を扱う.可能な設定値はFalseTrueAllの3つである.デフォルト値は,StringCasesStringCountではFalseStringPositionTrueである.

Overlaps->Falseとすると,マッチャーは最後にマッチした部分文字列の後もテストを続ける.
In[60]:=
Click for copyable input
Out[60]=
Overlaps->Trueとすると,マッチャーは最後にマッチした部分文字列の最初の文字に続く文字からマッチを続ける(単一のパターンが含まれるとき).
In[61]:=
Click for copyable input
Out[61]=
Overlaps->Allとすると,マッチャーは新たなマッチが見付からなくなるまで同じ場所からマッチを探し続ける.
In[62]:=
Click for copyable input
Out[62]=
複数のパターンがリストで与えられている場合,Overlaps->Trueとするとマッチャーは各パターンにつき一度ずつ同じ場所からマッチを行ってから次の文字に移る.
In[63]:=
Click for copyable input
Out[63]=
In[64]:=
Click for copyable input
Out[64]=
Overlaps->Trueとすると,パターンのリストを指定した場合と代替演算子()を使った場合では違いが生ずる.
In[65]:=
Click for copyable input
Out[65]=
In[66]:=
Click for copyable input
Out[66]=

StringPosition

StringPositionは,マッチする部分文字列の位置を返す他はStringCasesと同じような働きをする.
In[67]:=
Click for copyable input
Out[67]=
In[68]:=
Click for copyable input
Out[68]=
OverlapsオプションはデフォルトではTrueである(このオプションの詳細は前節を参照のこと).
In[69]:=
Click for copyable input
Out[69]=
空文字列でさえもマッチされる.
In[70]:=
Click for copyable input
Out[70]=

StringCount

StringCountは,(StringPositionあるいはStringCasesで求められる)マッチする部分文字列の数を返す.これは,マッチが多く,すべての部分文字列を保存するためのメモリ量が問題となる場合に便利である.
In[71]:=
Click for copyable input
Out[71]=
In[72]:=
Click for copyable input
Out[72]=

StringCountのデフォルトはOverlaps->Falseである.

StringReplace

StringReplaceは,与えられたパターンにマッチする部分文字列を代替するのに使われる
In[73]:=
Click for copyable input
Out[73]=
置換規則の右辺の文字列として名前付きパターンを使うことができる.RuleDelayed ()を使って時期尚早の評価を避ける点に注意のこと.
In[74]:=
Click for copyable input
Out[74]=
正規表現を使う場合は,右辺のはマッチする文字列全体を参照することを覚えておくと便利である.
In[75]:=
Click for copyable input
Out[75]=
第3引数を指定して置換数を制限することができる.
In[76]:=
Click for copyable input
Out[76]=
置換は文字列に限られない.結果が文字列でなければ,StringExpressionが返される.
In[77]:=
Click for copyable input
Out[77]=
In[78]:=
Click for copyable input
Out[78]//FullForm=

一般的な文字列パターンと関連して,旧を使う際のサポートは限られている.このオプションは廃止される予定なので,使用は避けるべきである.

StringReplaceList

StringReplaceListは,すべての可能な方法で単一の文字列置換が行われた文字列のリストを返す.
In[79]:=
Click for copyable input
Out[79]=
文字列のリストが入力として与えられると,出力は結果のネストしたリストになる.
In[80]:=
Click for copyable input
Out[80]=

StringSplit

StringSplitは,パターンにマッチする区切りで文字列を分割するのに便利である.デフォルトでは,分割は一連の空白文字の位置で行われる.
In[81]:=
Click for copyable input
Out[81]=
例えば,通常の文を単語に区切るのには,区切りに句読点も含まなければならない.
In[82]:=
Click for copyable input
Out[82]=
デフォルトにより,結果の冒頭と末尾にある空白文字列は移動される.
In[83]:=
Click for copyable input
Out[83]=
Allを第3引数として指定することで,これらを含めることができる.
In[84]:=
Click for copyable input
Out[84]=
第3引数は,文字列の最大区切り数を表す数でもよい.
In[85]:=
Click for copyable input
Out[85]=
これは,文字列を個々の行に分割する.
In[86]:=
Click for copyable input
Out[86]=
StartOfLineのように,位置にマッチするパターンで区切ることもできる.これは,結果に改行記号を残す.
In[87]:=
Click for copyable input
Out[87]=
規則を第2引数として使って,区切りあるいは区切りの一部分を出力に残すこともできる.
In[88]:=
Click for copyable input
Out[88]=
In[89]:=
Click for copyable input
Out[89]=
In[90]:=
Click for copyable input
Out[90]=
In[91]:=
Click for copyable input
Out[91]=
パターンや規則のリストを与えることもできる.パターンにマッチする区切りは結果から除かれる.
In[92]:=
Click for copyable input
Out[92]//InputForm=

Perlユーザのために

はじめに

一般的な文字列パターンを加えることで,Mathematica は一般的かつ日常的なプログラミングタスクにおいてPerlやPythonのような言語に変わる強力なものになった.次は,Perlのシンタックスや文字列操作に馴染んでいる人のための,同様な機能を Mathematica で使うための簡単な説明である.

以下はPerlに似た関数を構築するために使用される Mathematica 関数の概観である.

Perlコンストラクト
Mathematica 関数
説明
m/.../StringFreeQまたはStringCases文字列を正規表現でマッチする.サブパターンを抽出することもある
s/.../.../StringReplace正規表現にマッチする部分文字列を置換する
split(...)StringSplit正規表現にマッチする区切りの位置で文字列を分割する
tr/.../.../StringReplace文字を他の文字で置換する
/iIgnoreCase->Trueまたは"(?i)"大文字小文字の区別をしない限定子
/s"(?s)"が改行を含むすべての文字にマッチするように強制する
/x"(?x)"空白文字類を無視し,正規表現による拡張されたコメントを許容する
/m"(?m)"マルチラインモード(およびが行頭/行末に対応)

以下はPerlの一般的なコンストラクトのいくつかについてのより詳細な説明である.

m/.../

マッチ演算子が,文字列ににマッチする部分文字列が含まれているかどうかを検証する.Mathematica では,この種の簡単なマッチにStringFreeQを用いる.

次は,文字列で,の後ろにが含まれているかどうかを検証するためのPerlの断片である.
次は同様の検証を Mathematica で行う方法である.

マッチした文字列の一部に後でアクセスする必要がある場合は,Perlでは, , ...を用いる.Mathematica の関数で最もよいのは一般にStringCasesである.

次はエラーメッセージを抽出するPerlコードである.
次は Mathematica によるものである.
次は複数のサブパターンを一度に抽出するPerlのコードである.
Mathematica では,StringCasesを使ってこれを行う.
In[97]:=
Click for copyable input
Out[98]=
これは限定子を用いてすべてのマッチを配列に割り当てるのに似ている.
Mathematica では,StringCasesを用いて同じことが簡単に行える.
In[99]:=
Click for copyable input
Out[100]=

s/.../.../

Perlの代替演算子は Mathematica ではStringReplaceになる.
デフォルトのPerlの動作は単一置換である.
In[101]:=
Click for copyable input
Out[102]=
Perlの限定子はすべてのマッチを大域的に置換する.
In[103]:=
Click for copyable input
Out[103]=
評価の限定子を使うことで,Perlではサブパターンを置換の一部として使うことができる.これは Mathematica でも容易に行うことができる.
In[104]:=
Click for copyable input
Out[105]=

split(...)

Perlのコマンドは MathematicaStringSplitによく似ている.
In[106]:=
Click for copyable input
Out[107]=
Perlでも Mathematica でも,分割後のブロック数を指定することができる.
In[108]:=
Click for copyable input
Out[108]=
パターン中のカッコをとらえたは,とらえられた部分文字列が結果に含まれるのだが,Mathematica ではStringSplitの第2引数として規則を使うことで簡単に行うことができる.Perlに比べ,Mathematica では,これらの部分文字列に簡単に関数を適用できる.
In[109]:=
Click for copyable input
Out[110]//InputForm=
In[111]:=
Click for copyable input
Out[112]//InputForm=

tr/.../.../

Perlのコマンドは,Mathematica ではStringReplaceと規則のリストを一緒に使うことでまねることができる.

次はその最も簡単な形で,, , , , でそれぞれ置換されている.
次は MathematicaThreadを使った適切な規則を生成する.
In[113]:=
Click for copyable input
Out[114]=
次は,置換リストが文字のリストよりも短いために,がすべてで置換されている例である.
In[115]:=
Click for copyable input
Out[116]=
Perlにおける文字領域は,Mathematica ではCharacterRangeを用いてまねられる.
In[117]:=
Click for copyable input
Out[118]=
限定子を使うと,余分な文字が削除される.
In[119]:=
Click for copyable input
Out[120]=
限定子を使うと,文字リストの補完が使われる.
In[121]:=
Click for copyable input
Out[121]=
In[122]:=
Click for copyable input
Out[122]=
限定子は文字の任意の連なりを同じ文字に絞り込む.
MathematicaRepeated ()を使っても同じことができる.
In[123]:=
Click for copyable input
Out[124]=

例題

このセクションでは文字列パターンの実際的な例をいくつか取り上げる.

パターンのハイライト

これは,基底が1000のランダムなDNA配列である .
In[125]:=
Click for copyable input
Out[125]=
次で,特定のパターンにマッチするDNAの部分をハイライトする.
In[126]:=
Click for copyable input
Out[126]=
同様の結果を正規表現で出してみる.
In[127]:=
Click for copyable input
Out[127]=

HTMLの解析

文字列パターンは生のHTMLから情報を抽出するのに便利である.

これはwww.google.comから取ったソースである.
In[128]:=
Click for copyable input
In[129]:=
Click for copyable input
Out[129]=
ソースにある直接のハイパーリンクすべてを抽出してみる.
In[130]:=
Click for copyable input
Out[130]=
これは<...>というタグの内側にあるものをすべて削除する.
In[131]:=
Click for copyable input
Out[131]=

金額の検索

ここにあるテキストをスキャンしてドル表示の金額を表していると思われる文字列を抽出する.
In[132]:=
Click for copyable input
Out[132]=
上記を行う方法の1つに記号文字列パターンを使うものがある.
In[133]:=
Click for copyable input
Out[133]=
正規表現を用いて同じ結果を得る(ドル記号をエスケープするのを忘れないように).
In[134]:=
Click for copyable input
Out[134]=
この場合は組込みのパターンオブジェクトNumberStringを使うこともできる.
In[135]:=
Click for copyable input
Out[135]=

ファイル中のテキストの検索

これは,指定のパターンにマッチするテキストを含んだ行を検索する,グレップに似た非常に単純な関数である.
In[136]:=
Click for copyable input
これで,サンプルのテキストファイルを作る.
In[137]:=
Click for copyable input
Out[137]=
これは,中の数字を含む行と行番号を返す.
In[138]:=
Click for copyable input
Out[138]//TableForm=
これは,を単独の語として含んでいる行を検索する.
In[139]:=
Click for copyable input
Out[139]//TableForm=

効率的なマッチングのヒント

このセクションでは,文字列パターンマッチの効率に関する問題を扱う.

StringExpressionとRegularExpression

Mathematica のシンタックスで書かれた文字列パターンは,即座に正規表現に変換され,ついでコンパイル,キャッシュされるので,正規表現のシンタックスを直接使うのに対して Mathematica のシンタックスを使うことのオーバーヘッドはほとんどない.しかし例外として,多くの異なるパターンが何度か使われると明確なオーバーヘッドが起ることがある.

条件とパターンテスト

パターンにCondition ()あるいはPatternTest ()文が含まれていると,マッチングの間に Mathematica の評価装置が呼び出されるため,マッチングが遅くなる.上記のようなコンストラクトなしでパターンが書ける場合は,一般にこちらの方が速い.
In[140]:=
Click for copyable input
In[141]:=
Click for copyable input
Out[141]=
In[142]:=
Click for copyable input
Out[142]=

ネストした量限定子を避ける

マッチに使われている非決定性有限オートマトン(NFA)アルゴリズムのために,ネストした量限定子(あるいは正規表現でこれらに当たるもの等)を含んだパターンは非常に遅くなることがある.このようなパターンは,より効率のよいバージョンに「展開」することができる(詳しくはFriedl[2]を参照のこと).

関数を何度も呼び出すのを避ける

何らかのマッチを探して長いリストを検索しているなら,SelectStringMatchQ等を使うよりも,リスト全体を文字列関数に一度にフィードした方が効率が上がる(前述の辞書の例を参照されたい).次の例は,10字からなっている文字列を2000個生成し,その中からで始まりという部分文字列を含んだものを探し出す.
In[143]:=
Click for copyable input
In[144]:=
Click for copyable input
Out[144]=
こちらはSelectStringMatchQを使ったもので,速度が劣る.
In[145]:=
Click for copyable input
Out[145]=
StringMatchQにリスト全体を一度にフィードすると,ずっと速くなる.その後,Pickを使って希望の要素を抽出する.
In[146]:=
Click for copyable input
Out[146]=
また,StringCasesを使うこともできる.こちらも速い.が語頭にくるようにStartOfStringを使ってパターンを固定する必要がある(EndOfStringは,この例には過剰である).
In[147]:=
Click for copyable input
Out[147]=

通常の表現による検索を文字列検索に書き換える

文字列マッチングのアルゴリズムは,Mathematica が一般の式のマッチングに使うアルゴリズムとは異なるので(文字列マッチングは有限個のアルファベットと平坦な構造を仮定することができる等),通常の式のマッチングにおける問題を文字列マッチングの問題に置き換えて考えると都合がいいことがある.典型的な例として,記号の長いリストをが何度か現れるパターンとマッチさせる例を考える.

(例えば,1000000以降の)少なくとも4つの数字が同じ素数を見付けたい場合を例にとってみる.通常のパターンマッチングを使うと,次のようになるだろう.
In[148]:=
Click for copyable input
Out[148]=
整数のリストを文字列に変換することで,文字列マッチングが使えるようになる.
In[149]:=
Click for copyable input
Out[149]=
PickStringCasesを使うという前述のヒントに従って,さらにスピードアップを図ることができる.
In[150]:=
Click for copyable input
Out[150]=
In[151]:=
Click for copyable input
Out[151]=
長い文字列の場合は,違いが大きくなる.
In[152]:=
Click for copyable input
In[153]:=
Click for copyable input
Out[153]=
In[154]:=
Click for copyable input
Out[154]=
In[155]:=
Click for copyable input
In[156]:=
Click for copyable input
Out[156]=
In[157]:=
Click for copyable input
Out[157]=

実装の詳細

Mathematica における文字列パターンのマッチングは,Philip Hazel[1]によるPCRE(Perl準拠の正規表現)ライブラリの上に構築されている.

ところによっては5.1以前の Mathematica のアルゴリズムが使われている(例:パターンが単一の文字通りの文字列の場合等).

記号的文字列パターンはどれも,まず正規表現に変換される.この変換は内部的な関数を使って見ることができる.
In[158]:=
Click for copyable input
Out[158]//InputForm=

返される最初の要素は正規表現である.その他の要素は条件や置換規則,名前付きパターン等に関連するものでなければならない.

次に正規表現がPCREによってコンパイルされ,コンパイルされたものは,将来的に同じパターンが再び現れたときに使うためにキャッシュされる.記号的な文字列パターンから正規表現への変換は1度しか行われない.

パターンにおける Mathematica の条件は,PCREライブラリから Mathematica の評価装置の外部的呼び出しによって処理される.これによってマッチングが遅くなる.

一般的な文字列パターンに埋め込まれた明示的なRegularExpressionオブジェクトは,(キャプチャしないカッコで挟まれた)最終的な正規表現に組み継がれるので,名前付きパターンを数えると予想と食い違うかもしれない.

PCREは現在のところ文字コード規格255を超えるあらかじめセットされた文字クラスはサポートしていないので,単語と文字のクラス(WordCharacterLetterCharacter等)にはUnicodeの領域0-255にある文字コードのみが含まれる.このため,LetterCharacterおよび_?LetterQは文字コード規格255を超えた同等の結果は与えない.

PCREの同じような制限のため,(IgnoreCase->True等での)大文字小文字を区別しないマッチングはUnicodeの0-127の範囲にある文字(英語では通常--)にのみ適用される.

参考文献

[1] Hazel, P. "PCRE—Perl Compatible Regular Expressions." (2004). www.pcre.org

[2] Friedl, J. E. F. Mastering Regular Expressions, 2nd ed. O'Reilly & Associates, 2002.

New to Mathematica? Find your learning path »
Have a question? Ask support »