2015-10-25 7 views
5

を使用してトークン化、私は(非常に大まかprintfのような)の書式文字列をトークン化したいと私は私だけの小さなビットをしないのですと思う:PHP:正規表現(ほとんどが)

  • %の[番号] [1手紙ctYymd]はtoken²
  • $ 1。。$ 10はトークン
  • 他のすべてとなるものとなるものとする(通常のテキスト)がトークンになります。

私はかなり離れてthe regExp simulatorになりました。

²update:今の代わり%の#を使用して、それが何をすべきのようにこれが見えます。 (Windowsのコマンドラインパラメータと少ないトラブル)

enter image description here

あなたは(どちらか-かなど)のパイプで接続された3つの部分に焦点を当てている場合それはとても基本的にはそれだけで3試合だ、怖いではありません。私は最初から最後まで一致させたいので、私は/^...%/で物事を包み、1回以上繰り返すことが一致しないグループ(?:...囲ま:

$exp = '/^(?:(%\\d*[ctYymd]+)|([^$%]+)|(\\$\\d))+$/'; 

まだ私のソースが提供されていません。

$exp = '/^(?:(%\\d*[ctYymd]+)|([^$%]+)|(\\$\\d))+$/'; 
echo "expression: $exp \n"; 

$tests = [ 
     '###%04d_Ball0n%02d$1', 
     '%03d_Ball0n%02x$1%03d_Ball0n%02d$1', 
     '%3d_Ball0n%02d', 
    ]; 

foreach ($tests as $test) 
{ 
    echo "teststring: $test\n"; 
    if(preg_match($exp, $test, $tokens)) 
    { 
     array_shift($tokens); 
     foreach ($tokens as $token) 
      echo "\t\t'$token'\n"; 
    } 
    else 
     echo "not valid."; 
} // foreach 

私は結果が得られますが、:一致する順不同です。最初の%[番号] [手紙]は他の人が二重一致従って、一致しません:(OP編)

expression: /^((%\d*[ctYymd]+)|([^$%]+)|(\$\d))+$/ 
teststring: ###%04d_Ball0n%02d$1 
     '$1' 
     '%02d' 
     '_Ball0n' 
     '$1' 
teststring: %03d_Ball0n%02x$1%03d_Ball0n%02d$1 
not valid.teststring: %3d_Ball0n%02d 
     '%02d' 
     '%02d' 
     '_Ball0n' 
teststring: %d_foobardoo 
     '_foobardoo' 
     '%d' 
     '_foobardoo' 
teststring: Ball0n%02dHamburg%d 
     '%d' 
     '%d' 
     'Hamburg' 

答えて

2

ソリューション:私は2つのわずかな変化(のみについて「包装」)を使用:最初の検証のために、次いでトークン化のための:

#\d*[ctYymd]+|\$\d+|[^#\$]+ 

RegEx Demo

コード:

$core = '#\d*[ctYymd]+|\$\d+|[^#\$]+'; 
$expValidate = '/^('.$core.')+$/m'; 
$expTokenize = '/('.$core.')/m'; 

$tests = [ 
     '#3d-', 
     '#3d-ABC', 
     '***#04d_Ball0n#02d$1', 
     '#03d_Ball0n#02x$AwrongDollar', 
     '#3d_Ball0n#02d', 
     'Badstring#02xWrongLetterX' 
    ]; 

foreach ($tests as $test) 
{ 
    echo "teststring: [$test]\n"; 

    if(! preg_match_all($expValidate, $test)) 
    { 
     echo "not valid.\n"; 
     continue; 
    } 
    if(preg_match_all($expTokenize, $test, $tokens)) { 
     foreach ($tokens[0] as $token) 
      echo "\t\t'$token'\n"; 
    } 

} // foreach 

出力:

teststring: [#3d-] 
     '#3d' 
     '-' 
teststring: [#3d-ABC] 
     '#3d' 
     '-ABC' 
teststring: [***#04d_Ball0n#02d$1] 
     '***' 
     '#04d' 
     '_Ball0n' 
     '#02d' 
     '$1' 
teststring: [#03d_Ball0n#02x$AwrongDollar] 
not valid. 
teststring: [#3d_Ball0n#02d] 
     '#3d' 
     '_Ball0n' 
     '#02d' 
teststring: [Badstring#02xWrongLetterX] 
not valid. 
+1

ウォン-DER-FUL!どうもありがとうございます! 私の間違いを分析するには、 'preg_match'ではなく' preg_match_all'を実行します。なぜなら、単に間違っているからです一致しない外側のブラケットから私を救う。 –

+0

はい、そうです。 – anubhava

+0

私が紛失しているもの:誤った文字列で私を怒鳴りません。スキップするだけです。つまり、「Badstring%02xWrongLetterX」です。 –