Parantez daha regexp daha geribaşvuruları alın

6 Cevap php

Tamam bu İngilizce açıklamak gerçekten zor, bu yüzden ben sadece bir örnek vereyim.

Ben aşağıdaki biçimde dizeleri var gidiyorum:

key-value;key1-value;key2-...

ve ben bir dizi olarak veri ayıklamak gerekiyor

array('key'=>'value','key1'=>'value1', ... )

Ben bu işlevselliği (çoğu) ulaşmak için regexpi kullanmayı planlıyorsanız ve bu normal bir ifade yazdı:

/^(\w+)-([^-;]+)(?:;(\w+)-([^-;]+))*;?$/

preg_match ve bu kod ile çalışmak için:

for ($l = count($matches),$i = 1;$i<$l;$i+=2) {
    $parameters[$matches[$i]] = $matches[$i+1];
}

Giriş dizesi ilk ve son anahtar-değer çiftleri - Ancak sıradanifade açıkçası sadece 4 geribaşvuruları döndürür. Bu etrafında bir yolu var mı? Ben sadece dize doğruluğunu test ve mükemmel sonuçları ile döngüler PHP'nin explode kullanmak için regex kullanabilirsiniz biliyorum, ama ben düzenli ifadeler ile mümkün olup olmadığını gerçekten merak ediyorum.

Kısacası, ben normal ifadeler vasıtasıyla bir dize bu key-value; çiftleri bir keyfi sayıda yakalamak gerekir.

6 Cevap

Eğer sonuç çıkarmak ederken girişini doğrulamak için bir lookahead kullanabilirsiniz:

/\G(?=(?:\w++-[^;-]++;?)++$)(\w++)-([^;-]++);?/

(?=(?:\w++-[^;-]++;?)++$) doğrulama parçasıdır. Giriş geçersiz ise, eşleştirme hemen başarısız olur, ancak lookahead yine regex uygulandığı her zaman değerlendirilir alır. Anahtar-değer çiftleri ile senkronize (regex geri kalanı ile birlikte) tutmak için, ben \G önceki maç sona erdi noktaya her maç demirlemek için kullanılır.

Lookahead ilk defa başarılı olursa bu şekilde, bu sonraki her zaman başarılı olmak için garantili. Açıkçası bunun olabileceğini kadar verimli değil, ama muhtemelen bir sorun olmayacak - sadece test emin söyleyebilirim.

Ileri yönlü başarısız olursa, preg_match_all() sıfır (false) dönecektir. Eğer başarılı olursa, maçı diziler iade edilecektir: tam anahtar-değer çiftleri için bir tane, anahtarlar için bir tane, değerler için bir tane.

regex güçlü bir araçtır, ama bazen, onun en iyi yaklaşım değil.

$string = "key-value;key1-value";
$s = explode(";",$string);
foreach($s as $k){
    $e = explode("-",$k);
    $array[$e[0]]=$e[1];
}
print_r($array);

No Yeni karşılaşmalar büyük maçlar üzerine. Patlayan olduğunda Belki en limit bağımsız explode() yararlı olacaktır.

ne bu çözüm hakkında:

$samples = array(
    "good" => "key-value;key1-value;key2-value;key5-value;key-value;",
    "bad1" => "key-value-value;key1-value;key2-value;key5-value;key-value;",
    "bad2" => "key;key1-value;key2-value;key5-value;key-value;",
    "bad3" => "k%ey;key1-value;key2-value;key5-value;key-value;"
);

foreach($samples as $name => $value) {
    if (preg_match("/^(\w+-\w+;)+$/", $value)) {
        printf("'%s' matches\n", $name);
    } else {
        printf("'%s' not matches\n", $name);
    }
}

Ben çapa ihtiyaç olarak, doğrulama ve tek regexp ile veri çıkarma hem yapabilirsiniz sanmıyorum (^ ve $) doğrulama ve preg_match_all() Eğer birlikte çapa kullanırsanız veri için, ama preg_match_all() sadece eşleşen son seti dönecektir.