ドキュメンテーション センター

  • 評価版
  • 製品アップデート

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

動的正規表現

はじめに

動的表現では、regexp で一致させるパターンを入力文字列に基づいて作成できます。これにより、解析対象の文字列で、さまざまな入力パターンをより厳密に一致できます。動的表現は、関数 regexprep で使用される置換文字列でも使用できます。これによって、解析される入力に置換テキストを適応できるようになります。

これらのコマンドの引数 match_expr または replace_expr には、任意の数の動的表現を含めることができます。

regexp(string, match_expr)
regexpi(string, match_expr)
regexprep(string, match_expr, replace_expr)

動的表現の例として、次の regexprep コマンドでは、用語 internationalization が省略形の i18n に正確に置き換えられます。ただし、これを globalization のような別の語で使用するには、別の置換式を使用しなければなりません。

match_expr = '(^\w)(\w*)(\w$)';

replace_expr1 = '$118$3';
regexprep('internationalization', match_expr, replace_expr1)
ans =
    i18n
replace_expr2 = '$111$3';
regexprep('globalization', match_expr, replace_expr2)
ans =
    g11n

動的表現 ${num2str(length($2))} を使用すると、入力文字列に基づいて置換式を指定でき、毎回式を変更する必要がなくなります。この例では、動的置換構文 ${cmd} を使用します。

match_expr = '(^\w)(\w*)(\w$)';
replace_expr = '$1${num2str(length($2))}$3';

regexprep('internationalization', match_expr, replace_expr)
ans =
    i18n
regexprep('globalization', match_expr, replace_expr)
ans =
    g11n

解析する際に、動的表現は完全で有効な正規表現に対応していなければなりません。さらに、バックスラッシュ エスケープ文字 (\) を使用する動的一致表現は、2 つのバックスラッシュが必要です。1 つは式の初期解析に使用し、もう 1 つは完全な一致に使用します。動的表現を囲む丸かっこでは、キャプチャするグループを "作成しません"。

次の節で説明するように、動的表現には一致表現で使用できる形式が 3 つ、置換式に使用できる形式が 1 つあります。

動的一致表現 - (??expr)

(??expr) 演算子では表現 expr が解析され、結果が一致表現に挿入されます。次に、MATLAB® では修正された一致表現が評価されます。

次に、この演算子で使用できる表現の例を示します。

str = {'5XXXXX', '8XXXXXXXX', '1X'};
regexp(str, '^(\d+)(??X{$1})$', 'match', 'once');

このコマンドの目的は、入力セル配列に格納された各文字列で連続する文字 X を見つけることにあります。ただし、X の数は各文字列によって変わります。カウントが変化しない場合は、式 X{n} を使用して、これらの文字の n 個を一致させたいことを示します。ただし、一定値 n としてしまうと、この例ではうまく機能しません。

ここで使用する解決方法では、先頭のカウント数 (たとえば、セル配列の最初の文字列では 5) をトークンにキャプチャして、動的表現このカウントを使用しています。この例の動的表現は、(??X{$1}) です。ここで、$1 はトークン \d+ によってキャプチャされた値です。演算子 {$1} ではこのトークン値の数量子が作成されます。表現が動的であるので、同じパターンをセル配列の入力文字列の 3 つすべてに使用できます。最初の入力文字列で、regexp によって 5 つの X 文字が検索されます。2 番目の入力文字では、8 つの X 文字が検索されます。3 番目の入力文字では、X を 1 つだけ検索されます。

regexp(str, '^(\d+)(??X{$1})$', 'match', 'once')
ans = 
    '5XXXXX'    '8XXXXXXXX'    '1X'

一致表現を変更するコマンド - (??@cmd)

MATLAB では、(??@cmd) 演算子を使用して、一致表現に MATLAB コマンドの結果が含められます。このコマンドでは、一致表現内で使用できる文字列を返さなければなりません。

たとえば、動的表現 (??@flilplr($1)) を使用して、長い文字列の中にある「Never Odd or Even」という回文文字列が検索されます。

まず、入力文字列を作成します。すべての文字が小文字になるようにして、すべての語以外の文字を削除します。

str = lower(...
  'Find the palindrome Never Odd or Even in this string');

str = regexprep(str, '\W*', '')
str =
   findthepalindromeneveroddoreveninthisstring

動的表現を使用して、文字列内の回文を特定します。

palstr = regexp(str, '(.{3,}).?(??@fliplr($1))', 'match')
str =
   'neveroddoreven'

動的表現では文字列を構成する文字の順序が逆にされ、順序が逆になった文字列でできるだけ多くの一致を試みます。$1 の値はトークン (.{3,}) の値に依存しているので、これには動的表現が必要です。

MATLAB の動的表現では、現在アクティブなワークスペースにアクセスできます。つまり、ワークスペースの変数を変更するだけで、動的表現で使用される任意の関数や変数を変更できます。上の例の最後のコマンドを繰り返しますが、今度はベース ワークスペースに保存された関数ハンドルを使用して、式内で呼び出される関数を定義します。

fun = @fliplr;

palstr = regexp(str, '(.{3,}).?(??@fun($1))', 'match')
palstr =
   'neveroddoreven'

関数として機能するコマンド — (?@cmd)

(?@cmd) 演算子では、一致表現全体を解析する際に、regexp または regexprep で実行する、MATLAB コマンドが指定されます。MATLAB の他の動的表現とは異なり、この演算子が使用されている表現の内容は変更されません。代わりにこの機能を使用して、正規表現の内容の解析中に、どのようなステップが実行されているかを MATLAB にレポートさせることができます。この機能は正規表現を診断する際に便利です。

次の例は、ゼロ以上の文字の後に 2 つの同一の文字が続き、さらにゼロ以上の文字が続く部分が解析されます。

regexp('mississippi', '\w*(\w)\1\w*', 'match')
ans = 
    'mississippi'

一致を決定する際に MATLAB がとるステップを厳密に追跡するために、この例では短いスクリプト (?@disp($1)) を挿入して、最終的に一致する文字を表示します。この例ではグリーディ数量子が使用されているので、MATLAB では文字列でできるだけ多くの部分を一致するように試みられます。つまり、文字列の始めで一致が見つかっても、文字列の最後に到達するまで検索が続けられます。その後、文字 i から p と次の p に戻り、一致が最終的に満たされるのでその点で停止します。

regexp('mississippi', '\w*(\w)(?@disp($1))\1\w*', 'match')
i
p
p

ans = 
    'mississippi'

次に、再び同じ例を使って、今度は最初のレイジー数量子 (*?) を作成します。ここでも、MATLAB によって同じ一致が行われます。

regexp('mississippi', '\w*?(\w)\1\w*', 'match')
ans = 
    'mississippi'

ただし、動的スクリプトを挿入することによって、MATLAB による文字列の一致がかなり異なっていることがわかります。この場合、MATLAB では見つかった最初の一致が使用され、文字列の残りは考慮されません。

regexp('mississippi', '\w*?(\w)(?@disp($1))\1\w*', 'match')
m
i
s

ans = 
    'mississippi'

このような動的表現の柔軟性を示すために、次の例では、MATLAB で入力文字列を繰り返し解析して、セル配列を徐々に作成します。表現の最後にある演算子 (?!) は、実際には空の先読み演算子で、各繰り返しで強制的に失敗になります。MATLAB が表現の解決のためにとるステップを追跡するには、この強制的な失敗が必要です。

MATLAB では、入力文字列が何回も検索され、毎回異なる文字の組み合わせを試して、前回に見つかった一致よりも近い一致がないかどうかが確認されます。検索で一致が見つからない場合、検査結果は空の文字列になります。 動的なスクリプト (?@if(~isempty($&))) は、matches セル配列からこれらの文字列を除去します。

matches = {};
expr = ['(Euler\s)?(Cauchy\s)?(Boole)?(?@if(~isempty($&)),' ...
   'matches{end+1}=$&;end)(?!)'];

regexp('Euler Cauchy Boole', expr);

matches
matches = 
    'Euler Cauchy Boole'    'Euler Cauchy '    'Euler '    
'Cauchy Boole'    'Cauchy '    'Boole'

$& (または等価な $0)、$`、および $' の各演算子は、それぞれ入力文字列の現在の一致場所、その前にあるすべての文字、その後ろにあるすべての文字を示します。これらの演算子は、動的表現 (特に、(?@cmd) 演算子を使用する場合) を扱うときに便利なことがあります。

次の例では、文字 g を探して入力文字列を解析します。文字列での検索の各反復において、regexp によって現在の文字が g と比較され、見つからない場合は次の文字に進みます。この例では、^ 文字を使用して解析中の現在の位置をマークすることで、文字列のスキャンの過程を追跡します。

($` 演算子と 演算子では、現在解析している位置より前と後の文字列がキャプチャされます。 を文字列の中で指定する場合は、$'' のように単一引用符が 2 つ必要です。)

str = 'abcdefghij';
expr = '(?@disp(sprintf(''starting match: [%s^%s]'',$`,$'')))g';

regexp(str, expr, 'once');
starting match: [^abcdefghij]
starting match: [a^bcdefghij]
starting match: [ab^cdefghij]
starting match: [abc^defghij]
starting match: [abcd^efghij]
starting match: [abcde^fghij]
starting match: [abcdef^ghij]

置換式内のコマンド — ${cmd}

${cmd} 演算子では正規表現の置換文字列の内容が変更されるため、置換文字列を毎回変化する入力文字列のパラメーターに適応させることができます。MATLAB で使用される他の動的表現と同様に、全体的な置換式の中にこれらの表現をいくつでも含めることができます。

ここに示す regexprep の呼び出しでは、置換文字列は '${convertMe($1,$2)}' です。この場合、置換文字列全体は動的な表現です。

regexprep('This highway is 125 miles long', ...
          '(\d+\.?\d*)\W(\w+)', '${convertMe($1,$2)}');

この動的表現では、convertMe への呼び出しにおける入力引数として、一致した文字列から導かれた2 つのトークン (\d+\.?\d*)(\w+) を使用して、convertMe という名前の関数を実行するように、MATLAB に指示が送られます。$1$2 の値は実行時に生成されるので、置換文字列は動的表現を必要とします。

次の例では、長さや量を英単位系からメートル法に変換する convertMe という名前のファイルを定義します。

function valout  = convertMe(valin, units)
switch(units)
    case 'inches'
        fun = @(in)in .* 2.54;    uout = 'centimeters';
    case 'miles'
        fun = @(mi)mi .* 1.6093;  uout = 'kilometers';
    case 'pounds'
        fun = @(lb)lb .* 0.4536;  uout = 'kilograms';
    case 'pints'
        fun = @(pt)pt .* 0.4731;  uout = 'litres';
    case 'ounces'
        fun = @(oz)oz .* 28.35;   uout = 'grams';
end
val = fun(str2num(valin));
valout = [num2str(val) ' ' uout];
end

コマンド ラインで regexprep から関数 convertMe を呼び出し、変換する量と英単位系の名前の値を渡します。

regexprep('This highway is 125 miles long', ...
          '(\d+\.?\d*)\W(\w+)', '${convertMe($1,$2)}')
ans =
   This highway is 201.1625 kilometers long
regexprep('This pitcher holds 2.5 pints of water', ...
          '(\d+\.?\d*)\W(\w+)', '${convertMe($1,$2)}')
ans =
   This pitcher holds 1.1828 litres of water
regexprep('This stone weighs about 10 pounds', ...
          '(\d+\.?\d*)\W(\w+)', '${convertMe($1,$2)}')
ans =
   This stone weighs about 4.536 kilograms

以前の節で述べた (??@ ) 演算子と同様に、演算子 ${ } は現在アクティブなワークスペースの変数にアクセスできます。次の regexprep コマンドでは、ベース ワークスペースで定義された配列 A を使用しています。

A = magic(3)
A =
     8     1     6
     3     5     7
     4     9     2
regexprep('The columns of matrix _nam are _val', ...
          {'_nam', '_val'}, ...
          {'A', '${sprintf(''%d%d%d '', A)}'})
ans =
The columns of matrix A are 834 159 672

参考

| |

詳細

この情報は役に立ちましたか?