php

2010-10-15 22 views
5

'de negatif görünüm ve açgözlü niceleyiciler Herhangi bir URL'yi bulmak ve buna göre bağlantı kurmak için bir regex kullanıyorum. Bununla birlikte, zaten bağlantılı olan tüm URL'leri tek seferde vermek istemiyorum. Bu yüzden, URL'nin bir href'in daha önce bulunup bulunmadığını görmek için lookbehind kullanıyorum. Ancak bu, başarısız olur çünkü değişken uzunluk ölçücülerine göz atmaya ve PHP'ye yönelik görünümüne izin verilmez.php

/\b(?<!href\s*=\s*[\'\"])((?:http:\/\/|www\.)\S*?)(?=\s|$)/i 

Bu soruna en iyi yolu nedir:

İşte maç için düzenli ifade var?

DÜZENLEME:

Bunu test etmek için henüz var, ama tek bir regex bunu yapmaya hile PCRE tarafından desteklenen regex, içinde koşullu ifadeler kullanıldığını düşünüyorum. Böyle bir şey olacaktır:

/(href\s*=\s*[\'\"])?(?(1)^|)((?:http:\/\/|www\.)\w[\w\d\.\/]*)(?=\s|$)/i 

kilit noktası href yakalanır ise, maç nedeniyle derhal eşleşmiyor garantilidir şartlı (?(1)^|), dışarı atılır olmasıdır. Muhtemelen bir sorun var. Yarın test edeceğim. URL "> sona olmamasını sağlamak:

+4

Bir HTML ayrıştırıcısı kullanın ve yalnızca bir metin düğümü olduğunda bunu belirtin mi? – kennytm

+0

Bu muhtemelen en iyi çözümdür. Regex'i ayarlamanın bir yolu var mıydı diye merak ettim. –

+0

+1 güzel soru. – NikiC

cevap

1

Ben yuvarlak aynı şeyi başka bir yol yaparak çalıştı

/((?:http:\/\/|www\.)(?:[^"\s]|"[^>]|(*FAIL))*?)(?=\s|$)/i 

Ama oldukça hacky görünüyor benim için, ben daha iyisini yapabilirsin eminim.

İkinci yaklaşım seninkinden daha benzer olduğunu (ve böylece daha hassas olduğu):

/href\s*=\s*"[^"]*"(*SKIP)(*FAIL)|((?:http:\/\/|www\.)\S*?)(?=\s|$)/i 

Bir href= ben (*SKIP)(*FAIL) bulursanız. Bu, (*SKIP) ile karşılaştığında normal ifade motorunun bulunduğu konuma atladığım anlamına gelir.

Ama bu daha az hacky değil ve eminim ki daha iyi bir alternatif var.

+0

Ne hakkında '? =) – stevendesu

+0

@steven_desu: Bu yüzden ikinci versiyona bağlı kalacağım;) – NikiC

0

"Bağlantının parçası olmayan her URL" nin bulunması oldukça mantıklıdır. Her URL'yi, daha sonra bir bağlantı olan her URL'yi bulmak daha kolay olabilir ve önceki listeden her birini kaldırın.

Bildiğim kadarıyla URL'leri bulgu bir bağlantı bir parçası olarak, deneyin:

/<a([\s]+[\w="]+)*[\s]+href[\s]*=[\s]*"([\w\s:/.?+&=]+)"([\s]+[\w="]+)*>/i 

Emin olmak için http://regexpal.com/ ile test edilmiştir. Önce <a'u arar, ardından href ve ardından herhangi bir sayıdaki parametrenin izlediği herhangi bir sayıda parametreye izin verir. href yoksa, bir bağlantı değildir. Bir <a> etiketi değilse, bu bir bağlantı değildir. Bu sadece 'u diğer listeden (URL’ler) kaldırmak istediğimiz listenin bir listesi olduğundan, URL’nin tanımını [\w\s:/.?+&=]+ olarak basitleştirdim. Bir URL listesi oluştururken, daha akıllı bir şey isteyeceksiniz.