Regex Soru: sert veya yumuşak tırnak ile bu desen eşleştirme

5 Cevap php

Ben oldukça iyi çalışıyor regex yerini bu çapa var:

$p = '%<a.*\s+name="(.*)"\s*>(?:.*)</a>%im';

Bu <a bir boşluk ve name=" takiben şey sıfır veya daha fazla takip maçları

Bu bir sınıf ya da bir kimliği çapa adına öncesinde bile isimlerini kapma.

Ne ben eklemek istiyorum yanı sıra er ya da geç birileri bu yapmış çünkü bir tek tırnak (') ile name=' üzerine maç yeteneğidir.

Açıkçası ben sadece bunun için yazılmış bir ikinci regex ekleyebilirsiniz ama inelegant görünüyor.

Herkes tek teklifi eklemek ve sadece bir regex nasıl kullanılacağını biliyor musun? Başka iyileştirmeler veya öneriler çok hoş olurdu. Ben olsun tüm regex yardım kullanabilirsiniz!

Çok okuma için teşekkürler,

function findAnchors($html) {
    $names = array();
    $p = '%<a.*\s+name="(.*)"\s*>(?:.*)</a>%im';
    $t = preg_match_all($p, $html, $matches, PREG_SET_ORDER);
    if ($matches) {
        foreach ($matches as $m) {
            $names[] = $m[1];
        }
        return $names;
    }
}

5 Cevap

Bu deneyin:

/<a(?:\s+(?!name)[^"'>]+(?:"[^"]*"|'[^']*')?)*\s+name=("[^"]*"|'[^']*')\s*>/im

Burada sadece çevreleyen tırnak şerit var:

substr($match[1], 1, -1)

Ama böyle bir gerçek ayrıştırıcı kullanarak DOMDocument Bu düzenli ifade yaklaşım kesinlikle daha iyi olurdu.

James'in yorum aslında dize eşleştirme için kullanılan çok popüler, ama yanlış regex olduğunu. Bu dize sınırlayıcı kaçan izin vermez çünkü yanlış. Dize sınırlayıcı aşağıdaki regex çalışır "'ya da göz önüne alındığında

$regex = '([\'"])(.*?)(.{0,2})(?<![^\\\]\\\)(\1)';

\ 1, başlangıç ​​delimeter olan \ 2 içindekiler (eksi 2 karakter) ve \ 3 son 2 karakterler ve bitiş sınırlayıcı olduğunu. Bu regex sürece kaçış karakteri \ ve kaçış karakteri kaçan olmamıştır gibi sınırlayıcı kaçan sağlar. IE.,

'Valid'
'Valid \' String'
'Invalid ' String'
'Invalid \\' String'

[] karakter setleri maç için kullanın:

$p = "%<a.*\s+name=['\"](.*)['\"]\s*>(?:.*)</a>%im";

Geçerli çözüm 'adı' aşağıdaki diğer nitelikleri ile çapa maç olmayacak (örneğin <a name="foo" id="foo">).

Deneyin:

$regex = '%<a\s+\S*\s*name=["']([^"']+)["']%i';

This will extract the contents of the 'name' attribute into the back reference $1.
The \s* will also allow for line breaks between attributes.
You don't need to finish off with the rest of the 'a' tag as the negated character class [^"']+ will be lazy.

İşte başka bir yaklaşım var:

$rgx='~<a(?:\s+(?>name()|\w+)=(?|"([^"]*)"|\'([^\']*)\'))+?\1~i';

Bu soru eski olduğunu biliyorum, ama şimdi ortaya çıktı zaman ben Cookbook adlı deyim "onay kutularını boş yakalama grupları" için başka bir kullanım kadar düşündüm. İlk, sigara yakalayan grup isteksiz artı (+?) kontrolü altında, "isim = değer" çiftleri eşleştirme işler. Öznitelik adı anlamıyla ise name, boş grubu (()) hiçbir maçlar, sonra geribaşvuru (\1) döngünün kırılması, yine hiçbir şeyi maçları . (Geribaşvuru başarılı çünkü grup participated in the match, herhangi bir karakter tüketmek vermedi bile.)

Öznitelik değeri önceki yinelemenin yakalandı ne olursa olsun yazılmadan, grup 2. her zaman yakalanır. (Dal-reset yapı ((?|(...)|(...)) "yeniden kullanım" grup içinde 2. onlar tırnak hangisi tür, tırnak içindeki değeri yakalamak için için bize sağlar.) Döngü adı {[sonra kapanıyor yana (1)]} çıkageldi, son yakalanan değer bu niteliğin karşılık gelir.

See a demo on Ideone