Çift ayraç içine boru ayrılmış verileri ayrıştırmak için normal ifade

5 Cevap php

Ben böyle bir dize eşleştirmek çalışıyorum:

{{name|arg1|arg2|...|argX}}

Bir düzenli ifade ile

I preg_match ile kullanıyorum

/{{(\w+)\|(\w+)(?:\|(.+))*}}/

Ben daha iki bağımsız değişken her kullandığınızda ama, böyle bir şey olsun

Array
(
    [0] => {{name|arg1|arg2|arg3|arg4}}
    [1] => name
    [2] => arg1
    [3] => arg2|arg3|arg4
)

The first two items cannot contain spaces, the rest can. Perhaps I'm working too long on this, but I can't find the error - any help would be greatly appreciated.

Teşekkürler Jan

5 Cevap

Basit görevleri bu tür için düzenli ifadeler kullanmayın. Eğer gerçekten ihtiyacınız nedir:

$inner = substr($string, 2, -2);
$parts = explode('|', $inner);

# And if you want to make sure the string has opening/closing braces:
$length = strlen($string);
assert($inner[0] === '{');
assert($inner[1] === '{');
assert($inner[$length - 1] === '}');
assert($inner[$length - 2] === '}');

Buradaki sorun şudur: \ | (. +)

Düzenli ifadeler, varsayılan olarak, mümkün olduğu kadar çok karakter maç. Beri. ne istiyorsunuz değil mutlulukla çok eşleştirilir, | diğer örneklerini herhangi bir karakter vardır.

([^ \ | |] +) \ Sonuçlanan, | "dışında her şey maç" diyerek, ifadeden | Bunu önlemek için, dışlamak gerekir.

N argümanlar 1'den yerde için çalışması gerekir

<?php

$pattern = "/^\{\{([a-z]+)(?:\}\}$|(?:\|([a-z]+))(?:\|([a-z ]+))*\}\}$)/i";

$tests = array(
    "{{name}}"                          // should pass
  , "{{name|argOne}}"                   // should pass
  , "{{name|argOne|arg Two}}"           // should pass
  , "{{name|argOne|arg Two|arg Three}}" // should pass
  , "{{na me}}"                         // should fail
  , "{{name|arg One}}"                  // should fail
  , "{{name|arg One|arg Two}}"          // should fail
  , "{{name|argOne|arg Two|arg3}}"      // should fail
  );

foreach ( $tests as $test )
{
  if ( preg_match( $pattern, $test, $matches ) )
  {
    echo $test, ': Matched!<pre>', print_r( $matches, 1 ), '</pre>';
  } else {
    echo $test, ': Did not match =(<br>';
  }
}

Tabii ki böyle bir şey olsun istiyorum :) maçlar dinamik sayısını döndürmek için düzenli ifadede yolu yok - sizin durumunuzda savlar.

Yapmak istediğiniz ne baktığımızda, mevcut düzenli ifade ile tutmak ve sadece tarafından ekstra args patlamak gerektiği '|' ve bir argsdizi ekleyebilirsiniz.

Gerçekten de, bu PCRE kılavuzda şöyledir:

When a capturing subpattern is repeated, the value captured is the substring that matched the final iteration. For example, after (tweedle[dume]{3}\s*)+ has matched "tweedledum tweedledee" the value of the captured substring is "tweedledee". However, if there are nested capturing subpatterns, the corresponding captured values may have been set in previous iterations. For example, after /(a|(b))+/ matches "aba" the value of the second captured substring is "b".