2011-10-19 7 views
5

私はまだPHPについて多くのことを学んでいて、文字列の変更は興味深いものです。以前はpreg_matchを使ってメールアドレスの検証や質問の検索などを行ってきました。preg_match_all()はどのように文字列を処理しますか?

私はちょうどこの投稿What's wrong in my regular expression?から来て、なぜpreg_match_all関数が2つの文字列を生成したのか不思議でした。1つの文字の一部が取り除かれ、次にもう1つが目的の出力になりました。

私がこの機能について理解していることは、RegExを使用して文字列ごとに文字列を処理して、その処理を評価することです。このRegExは、最初の配列エントリをバイパスして、望ましい結果を生成するような方法で構造化できましたか?

ので、あなたは他のスレッド

$str = 'text^name1^Jony~text^secondname1^Smith~text^email1^example- 
     [email protected]~'; 

preg_match_all('/\^([^^]*?)\~/', $str, $newStr); 

for($i=0;$i<count($newStr[0]);$i++) 
{ 
    echo $newStr[0][$i].'<br>'; 
} 

echo '<br><br><br>'; 

for($i=0;$i<count($newStr[1]);$i++) 
{ 
    echo $newStr[1][$i].'<br>'; 
} 

この意志出力

^ジョニーズ〜
^スミス〜
^[email protected]~に行く必要はありません


ジョニーズ
スミス
[email protected]

2つの配列エントリの理由が、文字列の元のsytaxによるものか、それとも関数の通常の処理応答なのか不思議です。申し訳ありませんが、これがここにあるべきではありませんが、私は本当にこの作品が好奇心です。

おかげで、 ブロディ

+0

出力には常に、マッチ全体と、式内の各キャプチャグループのエントリが含まれます。 –

+0

答えはありませんが、ここで興味深いのは、より簡単な結果リストを返す 'PREG_SET_ORDER'フラグです。完全一致の '[0]'配列エントリを削除することはできませんが、正規表現で '\ K'を使用して内容を削除することができます。 – mario

答えて

2

それはするpreg_matchとpreg_match_allの標準的な動作だ - 「マッチした値」配列の最初の文字列があります正規表現パターンで捕捉されたFULL文字列。後続の配列値は 'キャプチャグループ'であり、その存在は正規表現パターンの()ペアの配置/位置に依存します。あなたの正規表現の場合、/\^([^^]*?)\~/

、完全な一致する文字列がmanual状態として

^ Jony ~ 
|  |  | 
^ ([^^]*?) ~ -> $newstr[0] = ^Jony~ 
       -> $newstr[1] = Jony (due to the `()` capture group). 
+0

ああ、私は理解しているので、最初にw/^で始まり〜で終わるテキストを見つけてから、()の2番目の式は、^マイナス〜の後のすべてを取ります。私は好奇心が私の最高を得ていると思います[^^] *? '^'の後にテキストをつかむように指示するのはなぜですか? '〜'をつかまえないのですか? – Brodie

+0

ですが、 '〜'はあなたのキャプチャグループの中にないので、 '[0]'セクションにしか表示されません。正規表現パターン全体をキャプチャグループと見なすことができるので、その仮想キャプチャは '[0]'に格納され、 '() 'で明示的に作成されたキャプチャは[1]、[2] –

+0

'[^^] *?'は、非貪欲な方法(?)ではなく、^([^^])ではな​​い多くの文字(*、 '0以上')に変換されます。 –

0

[0]はマッチ全体が含まれているが、あなたが配列構造を見るためにvar_dump($newStr)を行うことができます [1]部分だけ(あなたが抽出したい部分)...一方で、あなたはそれを把握しますよ。

$str = 'text^name1^Jony~text^secondname1^Smith~text^email1^example- 
     [email protected]~'; 

preg_match_all('/\^([^^]*?)\~/', $str, $newStr); 

$newStr = $newStr[1]; 
foreach($newStr as $key => $value) 
{ 
    echo $value."\n"; 
} 

これはに...なります(奇妙な結果は、表現を変更していない)

Jony 
Smith 
example- 
     [email protected] 
1

だろう、これは(デフォルトPREG_PATTERN_ORDERフラグのために)期待される結果です。 $newStrの最初のエントリにはすべての完全パターン一致が含まれ、次の結果はすべて最初のサブパターン(括弧内)に一致します。

+0

ああ今は意味がある...答えてくれてありがとう – Brodie

1

preg_match_allの結果の最初の配列は、あなたのケース/ \ ^([^^] *?)\〜/にあるpreg_match_all()関数に渡したパターン全体に一致する文字列を返します。結果の後続の配列には、パターン内の括弧の一致が含まれます。多分それは、例を理解することは簡単です:

$string = 'abcdefg'; 
preg_match_all('/ab(cd)e(fg)/', $string, $matches); 

$マッチする配列は最初の配列が、この場合は、全体のパターン、「ABCDEFG」の試合が含まれています

array(3) { 
    [0]=> 
    array(1) { 
    [0]=> 
    string(7) "abcdefg" 
    } 
    [1]=> 
    array(1) { 
    [0]=> 
    string(2) "cd" 
    } 
    [2]=> 
    array(1) { 
    [0]=> 
    string(2) "fg" 
    } 
} 

になります。 2番目の配列には、最初の括弧セット(この場合は 'cd')の一致が含まれます。 3番目の配列には、2番目の括弧セット(この場合は 'fg')の一致が含まれます。

2

このRegExは、最初の配列エントリをバイパスして目的の結果を生成するように構成されていますか?

絶対に。 assertionsを使用してください。この正規表現:中

preg_match_all('/(?<=\^)[^^]*?(?=~)/', $str, $newStr); 

結果:

Array 
(
    [0] => Array 
     (
      [0] => Jony 
      [1] => Smith 
      [2] => [email protected] 
     ) 

) 
0

あなたはこれがリアルタイムであなたの結果を示し、あなたpreg_match_all tester @ regextester.net

のような評価者を使用する必要がありますpreg_match_allの機能を想像する問題が発生したときはいつでも結果の順序、メタ命令、オフセットキャプチャなど、多くの機能を設定できます。

関連する問題