SenseTalk パターン言語の要素
SenseTalkパターン言語は、テキスト内の文字列マッチングに使えるパターンを定義するためのものです。 SenseTalkパターン言語の基本で説明したように、このパターンマッチング機能は、正規表現(regex)の上に構築されています。 SenseTalkパターン言語により、読みやすい構文でパターンを定義することが可能になります。
パターン定義においては、3桁の数字の出現といった単純なパターンも、 ある部分が任意だったり、代わりのものがあったり、長さが可変だったりする複雑なパターンも作成可能です。 どんなに単純なものであれ、複雑なものであれ、どのパターンも基本的なパターン要素の数々から構築されます。
ここからは、SenseTalkにおけるパターン構築に関して以下の情報を説明していきます。
パターン言語構文
SenseTalkパターン言語のパターン定義は、山括弧で囲まれたパターン記述(< ... >)で構成されます。
構文:
{pattern} < パターン言語式 >
ここで、パターン言語に付随するpatternという語は任意であり、通常は省略されます。
パターン定義(上記の構文でパターン言語式として表されるもの)は、連なった7つの数字の出現を検索する7 digitsのような1つの要素を取ることもありますが、 大半のパターンには要素(サブパターン)の連続が含まれます。 この連続を指定するときは、各サブパターンを次々と書き出してコンマまたはthenという語で区切るか、各要素を新しい行に列記して区切ります(もしくは、これらの組み合わせを使用します)。
したがって、下記の例は、どれも同じように社会保障番号のパターン定義を表していることになります。
<3 digits then "-", 2 digits then "-", 4 digits>
<3 digits, "-", 2 digits, "-", 4 digits>
<3 digits then "-"
2 digits, "-",
then 4 digits>
orという語を使用すると、サブパターンにおいて別の選択肢を指定することができます。 例:
<"cat" or "cow">
catまたはcowのいずれかにマッチします。
必要な場合、括弧を使って要素をグループ化することもできます。 例:
<"cat" or "cow" then 2 digits>
こちらはcat24またはcow17のようなテキストにマッチします が、
<"cat" or ("cow" then 2 digits)>
こちらはcat(数字不要)またはcow97のようなテキストのいずれかにマッチします。
パターン要素
パターン定義は、1つ1つの要素(サブパターン)から成り立っています。 要素としては、「cat」のような引用符で囲んだ文字列内の文字のほか、 SenseTalk変数や括弧に入った式なども使用可能です。以下のパターン定義要素表に示すパターン要素は、どれも要素として使用できるものです。
要素の定義方法に関する注記:
- ほとんどのパターン要素には、単数形と複数形があります。
- 単数形の要素は、厳密に1個の指定値にマッチします。
- 複数形の要素は、1個以上の指定値の連続にマッチします。
- 量指定子を使うと、要素がマッチするための文字または値の個数を明示的に操作することができます。
注:どのケースでも、characterはcharという形に、charactersはcharsという形に省略可能です。
量指定子と要素
letterやdigitなどの単数形のパターン要素を指定した場合、厳密にその種類の要素1個でパターンマッチが起こります。 lettersやdigitsなどの複数形を指定すると、その要素1個以上でマッチが起こることになります。
さらに、用意されている数々の量指定子を使うと、パターンマッチが起こるにあたって要素が現れるべき回数を指定することができます。
注:簡潔にするため、以下の記述では用語characterを使用していますが、どの要素の用語でも使用することが可能です。
厳密に1個の文字を指定する用語
character
a character
one character
exactly one character
例:
set myPattern to < "(" then a character then ")" >
マッチするパターン例: (w) ( ) (7) (.) ())
マッチしないもの:() (42) (salamander)その他のパターン
厳密な文字数を指定する用語
2 characters
exactly 2 characters
この例では2という数字を示していますが、正の整数であればどのような数字でも使用可能です。
例:
set myPattern to < "(" then 2 characters then ")" >
マッチするパターン例:(42) (CO) (())
マッチしないもの:() (w) ( ) (7) (.) ()) (salamander)その他のパターン
ゼロ個または1個の文字を指定する用語
maybe character
maybe a character
maybe one character
zero or one character
zero or maybe one character
例:
set myPattern to < "(" then maybe a character then ")" >
マッチするパターン例:() (w) ( ) (7) (.)
マッチしないもの:(42) (salamander)その他のパターン
注:このパターンでは、())もマッチ対象ですが、一部のコンテキストで全3文字のマッチが必要な場合を除き、()だけのマッチが優先されます。
1個以上の文字を指定する用語
characters
some characters
one or more characters
例:
set myPattern to < "(" then characters then ")" >
マッチするパターン例:(w) ( ) (7) (.) ()) (42) (salamander)
マッチしないもの:()その他のパターン
下の例の文では、(a woman)と(her cat)の2つの文字列がマッチします。
ゼロ個以上の文字を指定する用語
maybe characters
maybe some characters
zero or more characters
例:
set myPattern to < "(" then zero or more characters then ")" >
マッチするパターン例:() (w) ( ) (7) (.) (42) (salamander)
マッチしないもの:その他のパターン
注:このパターンでは、())もマッチ対象ですが、全3文字のマッチが必要な場合を除き、()だけのマッチが優先されます。
下の例の文では、(a woman)と(her cat)の2つの文字列がマッチします。
文字の最小個数を指定する用語
at least 2 characters
2 or more characters
2 or maybe more characters
at least 2 or more characters
at least 2 and maybe more characters
この例では2という数字を示していますが、正の整数であればどのような数字でも使用可能です。
例:
set myPattern to < "(" then 2 or more characters then ")" >
マッチするパターン例:(42) (salamander)
マッチしないもの:() (w) ( ) (7) (.) ())その他のパターン
下の例の文では、(a woman)と(her cat)の2つの文字列がマッチします。
文字の最小個数と最大個数を指定する用語
2 to 4 characters
from 2 to 4 characters
この例では2~4という範囲を示していますが、正の整数であればどのような範囲でも使用可能です。
例:
set myPattern to < "(" then 2 to 4 characters then ")" >
マッチするパターン例:(42)
マッチしないもの:() (w) ( ) (7) (.) ()) (salamander)その他のパターン
Lazy(ものぐさな)量指定子vs. Greedy(欲張りな)量指定子
マッチ対象の値の個数が可変のパターンを作成する場合、lazyまたはgreedyマッチのいずれかを選択可能です。 lazyサブパターンマッチは、全体的なパターンへのマッチを維持しながら、できる限り少数の出現でマッチを行うものです。 greedyサブパターンマッチは、できる限り多数でマッチを行います。
SenseTalkのパターンマッチはデフォルトでlazyになっています。 したがって、次のパターンは、
< "(" , characters , ")" >
「(」 で始まり、その後に1個以上の文字が続いてから、最初に出現する「)」 までを含んだ一続きにマッチします。 一方、こちらのパターンは、
< "(" , lots of characters , ")" >
「(」で始まり、その後にできる限り多くの文字を欲張って消費し、ソーステキスト内で一番最後に出現する「)」 までを含んだ一続きにマッチします。
この違いを分かりやすく示すために、次の例文を考えてみましょう。
Amy (a woman) and Flossie (her cat) lie down to take a nap.
パターンは次のとおりです。
< "(" then one or more characters then ")" >
さて、この例文を変数myTextに読み込むと、次のコードは2つの値を返します。
set myPattern to < "(" then one or more characters then ")" >
put every occurrence of myPattern in myText into myList
put mylist
出力: ((a woman),(her cat))
このように働くのは、SenseTalkにおいてone or more charactersがlazy(パターンを満たす必要最小限の文字数を消費する設定)になっているためです。
しかし、時にはgreedyマッチが必要な場合もあるかもしれません。 この例でgreedyの振る舞いを実現するには、パターンを次のように変更します。
< "(" then one or preferably more characters then ")" >
可能であれば文字数の多いパターンマッチの方を優先する旨を指定することにより、今度はevery occurrence of myPattern in myText式が、最初の「(」から最後の「)」までのすべてを含んだ、次の1つの値だけを返します。
(a woman) and Flossie (her cat)
ゼロ個または1個の文字を指定しつつ、1個の方を優先する用語
preferably character
preferably a character
preferably one character
zero or preferably one character
例:
set myPattern to < "(" then preferably a character then ")" >
マッチするパターン例:() (w) ( ) (7) (.) ())
マッチしないもの:(42) (salamander)その他のパターン
注:())というパターンが現れた場合、欲張って全3文字にマッチします。ただし、そのコンテキストにおいて、2番目の ) が後続部のパターンを満たすのに必要な場合は別です。その場合は、単に()にマッチします。
1個以上の文字を指定しつつ、できる限り多数の文字を優先する用語
lots of characters
preferably lots of characters
one or lots of characters
one or preferably lots of characters
one or preferably more characters
例:
set myPattern to < "(" then lots of characters then ")" >
マッチするパターン例:(w) ( ) (7) (.) ()) (42) (salamander)
マッチしないもの:()その他のパターン
上の例の文では、(a woman) and Flossie (her cat)にマッチします。
ゼロ個以上の文字を指定しつつ、できる限り多数の文字を優先する用語
preferably characters
maybe lots of characters
zero or lots of characters
zero or preferably lots of characters
zero or preferably more characters
例:
set myPattern to < "(" then zero or preferably more characters then ")" >
マッチするパターン例:() (w) ( ) (7) (.) ()) (42) (salamander)
マッチしないもの:その他のパターン
注:検索で())が現れた場合、このパターンは欲張って全3文字にマッチします。ただし、そのコンテキストにおいて、2番目の ) が後続部のパターンを満たすのに必要な場合は別です。その場合は、単に()にマッチします。
上の例の文では、(a woman) and Flossie (her cat)の1文字列にマッチします。
文字の最小個数を指定しつつ、できる限り多数の文字を優先する用語
at least 2 or lots of characters
2 or lots of characters
2 or preferably lots of characters
2 or preferably more characters
at least 2 and preferably lots of characters
at least 2 and preferably more characters
この例では2という数字を示していますが、正の整数であればどのような数字でも使用可能です。
例:
set myPattern to < "(" then 2 or preferably more characters then ")" >
マッチするパターン例:(42) (salamander)
マッチしないもの:() (w) ( ) (7) (.) ())その他のパターン
上の例の文では、(a woman) and Flossie (her cat)の1文字列にマッチします。
文字の最小および最大個数を指定しつつ、できる限り多数の文字を優先する用語
2 to 4 characters greedily
from 2 to 4 characters greedily
この例では2~4という範囲を示していますが、正の整数であればどのような範囲でも使用可能です。
例:
set myPattern to < "(" then from 2 to 4 characters greedily then ")" >
マッチするパターン例:(42)
マッチしないもの:() (w) ( ) (7) (.) ()) (salamander)その他のパターン
GreedyまたはLazyな振る舞いを明示的に強制する
可変の文字数を表す用語の後にgreedilyまたはlazilyという用語を使用すると、greedyまたはlazyな振る舞いを明示的に強制することができます。 これらの用語は、使用した場合、先行する用語の通常の振る舞いに関係なく常に優先されます。
この振る舞いを分かりやすく示した例をいくつか挙げます。
maybe a character greedily -- ゼロ個または1個、ただし1個を優先
some characters greedily -- 1個以上、ただしできる限り多数を優先
lots of characters greedily -- 1個以上、ただしできる限り多数を優先(通常の振る舞いを明示)
lots of characters lazily -- 1個以上、ただしできる限り少数を優先(通常の振る舞いをオーバーライド)
Greedyのシノニム
以下に紹介する用語はすべて、greedy量指定子を指定する際に互換的に使用できるものです。
lots
lots of
many
max
maximum
the maximum number of
the most
パターンにおける大文字小文字の区別
式のところで説明したように、SenseTalkにおけるテキスト比較は通常、大文字と小文字を区別しません。 この振る舞いは、パターンマッチにも当てはまります。 したがって、パターンで英字を検索する場合、大文字か小文字かに関わらずマッチが起こります。 the caseSensitiveローカルプロパティを使うと、大文字小文字が区別されるよう、このデフォルトの振る舞いを変更することができます。
ほとんどの比較演算子では、演算子のオプションとして直接、大文字小文字の区別を指定することができます。これはグローバル設定を上書きします。 これらのオプションは、通常のテキスト比較だけでなく、パターン比較にも適用されます。以下に例を挙げます。
put <3 chars from "ABCDEF"> matches "fab" --> True
put <3 chars from "ABCDEF"> matches "fab" case sensitive --> False
パターン内で大文字小文字の区別を設定する
大文字小文字の区別に関する設定をパターン定義に直接組み込むこともできます。 このインライン設定は、デフォルト設定やコマンドで指定したオプションよりも常に優先されます。 このオプションをパターン内に含めることで、パターンの部分ごとに大文字小文字の区別をきめ細かく管理することができます。
大文字小文字の区別要素の構文:
case sensitive -- 後続のすべてのパターン要素で大文字と小文字が必ず区別されます
case insensitive -- 後続のすべてのパターン要素で大文字と小文字が区別されなくなります
case sensitive: 要素 -- 指定された要素で大文字と小文字が必ず区別されます
case insensitive: 要素 -- 指定された要素で大文字と小文字が区別されなくなります
case sensitive: ( サブパターン ) -- 指定されたサブパターンで大文字と小文字が必ず区別されます
case insensitive: ( サブパターン ) -- 指定されたサブパターンで大文字と小文字が区別されなくなります
注:case sensitiveで表される箇所には、次のシノニムを使うこともできます。case-sensitive、caseSensitive、considering case、with case
case insensitiveで表される箇所には、次のシノニムを使うこともできます。case-insensitive、caseInsensitive、ignoring case、without case
例:
put "abc" matches <case sensitive, 3 chars from "DCBA"> --> False
例:
set partNum to <"ABC", digit, case-sensitive: char in "JQXZ", digit>
put partNum matches "Abc9Q2" --> True(「ABC」には大文字小文字の区別はないため)
put partNum matches "ABC7x3" --> False(「x」が大文字でないため)
例:
set code to <with case, character of "ABC", ignoring case, character of "XYZ">
put "aZ" matches code --> False(マッチするためには「a」が大文字でなければなりません)
put "Bx" matches code --> True(「x」は大文字でも小文字でも構いません)
注:大文字小文字の区別指示子(ある場合)は、実質的にはパターン定義自体の一部ではなく、適用される定義全体に影響を与えるものです。 したがって、大文字小文字の区別値を指定しても、パターンマッチの対象となるソーステキストからの文字は消費されません。