OT: PCRE match vsetko okrem danych slov..?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Matúš Matula
Člen | 257
+
0
-

Chcel by som mat url v tvare novinky/list a novinky/nazovnovinkyXYZ .
Vie mi niekto poradit, ako sa da napisat PCRE matchni vsetko okrem slov ‚detail‘ a ‚list‘ ? Myslim, ze keby som to dal k <id> do routy , tak by to chodilo

P.S. skusal som co som vedel, ale s regularmi sa moc nekamosim :-)

<?php

$router[] = new Route('<lang>/' . $prefix . 'novinky/[<id [REGEXP]>/][<action>/]', array(
			'module' => 'News:Front',
			'presenter' => 'Default',
			'action' => 'detail',
			'lang' => NULL,
			'id' => array(
                Route::FILTER_IN => callback('NewsSeoModel::findIdByUri'),
                Route::FILTER_OUT => callback('NewsSeoModel::findUriById'),
	        ),
		));

?>
srigi
Nette Blogger | 558
+
0
-

Matúš Matula napsal(a):

Vie mi niekto poradit, ako sa da napisat PCRE matchni vsetko okrem slov ‚detail‘ a ‚list‘?

preg_match('~[^(detail)|(list)]~', $subject);
Matúš Matula
Člen | 257
+
0
-

Dik, to som skusal, ale chova sa to akosi divne (pre mna :)

<?php

$subject = 'detai2l';
var_dump(preg_match('~[^(detail)|(list)]~', $subject)); // => 1 - OK

$subject = 'detaidl';
var_dump(preg_match('~[^(detail)|(list)]~', $subject)); // => 0 - wtf?

?>
newPOPE
Člen | 648
+
0
-

nestaci ?

<?php
	var_dump(! preg_match('/(detail|list)/', $subject));
?>
kravčo
Člen | 721
+
0
-

Trochu dosť zlý regulár :) niekto sa nám tu nevyspal?

správne:

/^(?:(?!detail)......|(?!list)....|.*)$/

matchne čokoľvek okrem 'detail' a 'list'.

pre zaujímavosť:

~[^(detail)|(list)]~

vyhovie na všetkých reťazcoch, ktoré obsahujú aspoň jeden znak iný než jeden spomedzi

(
d
e
t
a
i
l
)
|
s

Tvoj prvý pokus vyhovie – obsahuje '2'.


Na druhej strane, tebe by možno lepšie poslúžilo posunúť action do query parametra – teda napísať routovaciu masku takto:

'<lang>' . $prefix . 'novinky/<id> ? <action>'

Myslím, že teraz ani nebude treba hranaté zátvorky…

Matúš Matula
Člen | 257
+
0
-

Diky kravčo,

skúšal som ten regulár, ale zdá sa mi, že nem dobre :)

Tie bodky som moc nepobral, môžeš mi to trošku objasniť prosím?
obidva výstupy matchnú ‚detail‘ aj ‚list‘ a vlastne asi úplne všetko :)

<?php

$subject = 'detail';

var_dump(preg_match('/^(?:(?!detail)|(?!list)|.*)$/', $subject));
var_dump(preg_match('/^(?:(?!detail)......|(?!list)....|.*)$/', $subject));
?>
nAS
Člen | 277
+
0
-

Podle mě by tam neměly být ty ořítka:

/^(?:(?!detail)(?!list).*)$/

Matchne vše co nezačíná na detail a list.


Ale já bych udělal normálně 2 routy:

  1. novinky\list která povede na News:list
  2. novinky\<id> která povede na News:detail($id)

a máš to bez problému.

Matúš Matula
Člen | 257
+
0
-

nAS dik!
2 routy mam aj ja, len som spekuloval, ci to pojde aj do 1 nacpat, lebo to mam v moduloch a ked budem mat 8modulov v app a kazda min. 2 routy.. :-)Ale zatial ma to nepali, kazdopadne dik

kravčo
Člen | 721
+
0
-

Matúš Matula napsal(a):

Diky kravčo,

skúšal som ten regulár, ale zdá sa mi, že nem dobre :)

Posral som to aj ja, .* na záver samozrejme matchne všetko :)

toto by už malo byť presné (a dlhé, ťažko čitateľné, prakticky nepoužiteľné)

/^(?:.{0,3}|(?!list)....|.....|(?!detail)......|.{7,})$/

Tie bodky som moc nepobral, môžeš mi to trošku objasniť prosím? obidva výstupy matchnú ‚detail‘ aj ‚list‘ a vlastne asi úplne všetko :)

Bodka znamená matchni akýkoľvek znak. V tomto výraze sú bodky spojené s tzv. negative zero-width lookahead assertion (viac perlre alebo php pcre). Čiže tvoria dvojku (?!text).... (bodiek je toľko, koľko znakov je v reťazci text). Takáto dvojka matchne čokoľvek štvorpísmenové okrem 'text'.

Regulár teda matchuje všetky vstupy dĺžky 0–3, 5, 7+ a pre tie dĺžky 4 resp. 6 len rôzne od 'list' resp. 'detail'.

nAS napsal(a):

Podle mě by tam neměly být ty ořítka:

/^(?:(?!detail)(?!list).*)$/

Matchne vše co nezačíná na detail a list.

Áno, teda matchne aj 'detailny-popis-nove-ficury', či 'listova-posta-umiera'. Je otázka, či to problém je, alebo nie…