正規表現における先読みアサーション
先読みアサーション
正規表現では、次の 2 種類の前後参照アサーションがあります。先読みと後読みです。両方とも、アサーションが式との一致を返すために満たさなければならない条件になります。
"先読み" アサーションは (?=test) という形式で、正規表現内の任意の場所に置くことができます。MATLAB® はテキストの現在の位置からテスト条件を先読みします。MATLAB でテスト条件を一致させる場合、残りの式も続けて処理して一致部分を見つけます。
たとえば、パスを指定する文字ベクトルで先読みを行い、プログラム ファイル (ここでは、fileread.m) を含むフォルダー名を検索します。
chr = which('fileread')
chr =
'matlabroot\toolbox\matlab\iofun\fileread.m'
regexp(chr,'\w+(?=\\\w+\.[mp])','match')
ans =
1×1 cell array
{'iofun'}
一致の式 \w+ は、1 つ以上の英数字またはアンダースコア文字を検索します。regexp がこの条件と一致する語句を検出するたびに、バックスラッシュ (2 つのバックスラッシュ \\ で指定されます) の後にファイル名 (\w+) と .m または .p の拡張子 (\.[mp]) が続く語句を先読みします。関数 regexp は、先読み条件を満たす一致を返します (ここでは、フォルダー名 iofun)。
オーバーラップの一致
先読みアサーションでは、テキストの中の文字を処理済みにしません。そのため、それを使用してオーバーラップする文字列を検索します。
たとえば、最初の文字とその後にさらに 5 文字続くテキストの一致を行い、文字ベクトル内の空白以外の 6 文字のテキストを "すべて" 検出します。
chr = 'Locate several 6-char. phrases'; startIndex = regexpi(chr,'\S(?=\S{5})')
startIndex =
1 8 9 16 17 24 25
開始インデックスは、次のフレーズに対応します。
Locate severa everal 6-char -char. phrase hrases
先読み演算子がないと、MATLAB は文字ベクトルを左から右に解析し、解析の進行と同時にベクトルが処理済みになっていきます。一致する文字が見つかると、regexp でその場所が記録され、最後に一致した文字の場所から文字ベクトルの解析が再開されます。このプロセスでは文字がオーバーラップして解析されることはありません。
chr = 'Locate several 6-char. phrases'; startIndex = regexpi(chr,'\S{6}')
startIndex =
1 8 16 24
開始インデックスは、次のフレーズに対応します。
Locate severa 6-char phrase
論理 AND 条件
もう 1 つの先読み演算の用途は、2 つの条件間で論理演算 AND を実行する場面です。次の例では、最初に、関数 normest のヘルプの先頭 50 文字から成る文字配列内で、すべての小文字の子音の検出を試行しています。
helptext = help('normest');
chr = helptext(1:50)
chr =
' NORMEST Estimate the matrix 2-norm.
NORMEST(S'
母音以外 ([^aeiou]) を探すだけでは、出力に大文字、空白文字、句読点が含まれるので、期待する答えを得られません。
c = regexp(chr,'[^aeiou]','match')
c =
1×43 cell array
Columns 1 through 14
{' '} {'N'} {'O'} {'R'} {'M'} {'E'} {'S'} {'T'} {' '} {'E'} {'s'} {'t'} {'m'} {'t'}
Columns 15 through 28
{' '} {'t'} {'h'} {' '} {'m'} {'t'} {'r'} {'x'} {' '} {'2'} {'-'} {'n'} {'r'} {'m'}
Columns 29 through 42
{'.'} {'↵'} {' '} {' '} {' '} {' '} {'N'} {'O'} {'R'} {'M'} {'E'} {'S'} {'T'} {'('}
Column 43
{'S'}
先読み演算子を使用し、次の AND 条件を作成して、再度試してみます。
(lowercase letter) AND (not a vowel)
今度は、結果が正しくなります。
c = regexp(chr,'(?=[a-z])[^aeiou]','match')
c =
1×13 cell array
{'s'} {'t'} {'m'} {'t'} {'t'} {'h'} {'m'} {'t'} {'r'} {'x'} {'n'} {'r'} {'m'}
先読み演算子を使用して AND を実行する際には、テスト式 test の "後に" 一致させる式 expr を配置しなければなりません。
(?=test)expr or (?!test)expr