Newsgroup: it.comp.www.php
Titolo: regex: individuare determinati caratteri e solo quelli

ciao a tutti e buon anno!
Sto cercando di trovare una regexp che mi individui se una stringa
contiene una combinazione qualsiasi dei seguenti caratteri, e
SOLAMENTE di questi:
+ - && || ! ( ) { } [ ] ^ " ~ * ? : \
esempio:
+     SI
++   SI
+ && ***    SI
+parola *altraparola    NO
Ho provato (usando preg) con questo pattern, usando i word boundaries
$pattern = '/\b[\+]+\b/';
ma non funziona come vorrei
Potreste darmi qualche suggerimento?
grazie mille, ciao!

 + - && || ! ( ) { } [ ] ^ " ~ * ? : \
La butto li`:
/^[\+\-\&\|\!\(\)\{\}\[\]\^\"\~\*\?\:\\\ ]+$/
Bye.

 /^[\+\-\&\|\!\(\)\{\}\[\]\^\"\~\*\?\:\\\ ]+$/
ciao,
non copre completamente tutti i casi :
esempio (returned TRUE significa che NON ha matchato, mentre FALSE
significa che ha matchato...)
effettivamente questa funzione mi serve per VALIDARE la stringa di
input, la quale è valida solo se NON contiene combinazioni di quei
caratteri isolati come fossero parole... spero di essermi
spiegato !!!
+scuola => returned TRUE
++scuola => returned TRUE
scuola +privacy => returned TRUE
scuola privacy+ => returned TRUE
scuola +privacy+ => returned TRUE
+scuola privacy => returned TRUE
+scuola +privacy => returned TRUE
+scuola privacy+ => returned TRUE
+scuola +privacy+ => returned TRUE
scuola+ => returned TRUE
scuola++ => returned TRUE
scuola+ privacy => returned TRUE
scuola+ privacy+ => returned TRUE
scuola+ +privacy => returned TRUE
scuola+ +privacy+ => returned TRUE
+scuola+ +privacy+ => returned TRUE
+ scuola => returned TRUE but was expecting FALSE
++ scuola => returned TRUE but was expecting FALSE
scuola + => returned TRUE but was expecting FALSE
scuola ++ => returned TRUE but was expecting FALSE
+ => returned FALSE
++ => returned FALSE
+ + => returned FALSE
+ ++ => returned FALSE

spiegato !!!
Adesso si', prima no :-)
Quello che vuoi dire dovrebbe essere: "+, * ecc. vanno bene solo se
in sequenza adiacente a un carattere alfabetico".
Quindi non deve essere vero che la stringa contiene quei caratteri,
adiacenti SOLO a caratteri DIVERSI da [a-z].
Nel caso semplice (++pippo e --pippo sono accettati, e quindi anche
+-pippo e -+pippo sono accettati) fai cosi', altrimenti uno bisogna
tiri in ballo le backreference (non ho provato, ma forse sarebbe un
qualcosa come "/[^a-z$seq]([$seq])(\1*)[^a-z$seq]/"):
<?php
        function validate($string)
        {
                $seq    = '+\*\-\/';
                return !preg_match("/[^a-z$seq][$seq]+[^a-z$seq]/",
		// Gli spazi sono un modo sporco per togliermi dalla
		// situazione speciale di inizio e fine stringa
			" $string ");
        }
        $tests  = array(
                '+scuola ', '++scuola ', 'scuola +privacy ', 'scuola
privacy+ ',
                'scuola +privacy+ ', '+scuola privacy ', '+scuola +privacy
',
                '+scuola privacy+ ', '+scuola +privacy+ ', 'scuola+ ',
'scuola++ ',
                'scuola+ privacy ', 'scuola+ privacy+ ', 'scuola+ +privacy
',
                'scuola+ +privacy+ ', '+scuola+ +privacy+ ', '+ scuola ',
                '++ scuola ', 'scuola + ', 'scuola ++ ', '+ ', '++ ', '+ +
', '+ ++ '
        );
        foreach($tests as $test)
                print "$test returned " . (validate($test) ?
'TRUE':'FALSE') . "<br />";
?>
Leonardo
-- 
And where the black and corkscrew towers climb,
Lost and athirst the ragged pack abides,
Old as the aeons, trapped in tombs of time,
Sailing the tortuous temporal tides


Funziona ma vanno aggiunte anche le maiuscole, le accentate più tutti
i caratteri ASCII non compresi. Ad esempio +Scuola ritorna FALSE.
Cioè, la tua re va per esclusione, cerca i casi non voluti, che sono
molteplici e magari anche imprevedibili.
Questa invece /(\s(\+|\*|\&)+\s)/ funziona al contrario, cerca solo le
sequenze volute, ho messo i caratteri +,*,& (gli altri basta
aggiungerli).
Ah, anche nella mia c'è la zozzata degli spazi prima e dopo, si può
evitare scrivendo una re più complessa oppure, banalmente, prima del
controllo aggiungi uno spazio prima e dopo (sono abbastanza seguace
della eXtreme Programming ;-)
d

 i caratteri ASCII non compresi. Ad esempio +Scuola ritorna FALSE.
per le maiuscole basta aggiungere una i dopo la regexp:
preg_match("/...../i",....);
per il resto, mi sono incastrato e mi fa fatica scastrarmi :)

aggiungerli).
Ma, se gli mandi "+Scuola ++, +Privacy", cosa risponde la tua?


 Ah, anche nella mia c'è la zozzata degli spazi prima e dopo,
Questa funziona solo se faccio l'arteficio degli spazi !
$q = " $q ";
$matches = preg_match($pattern, $q);
Cavolaccio ma possibile? :-)
Per ridirlo in altre parole, il mio obiettivo è individuare i "token"
isolati (cioè separati da spazi) composti da una sequenza di quei
caratteri.
Se nella mia stringa c'è uno di questi token, allora la validazione
deve essere FALSE.
Esempio: "pippo  *   pluto"
C'è il token "*" in mezzo per cui la regexp lo deve individuare.
Mi sta venendo in mente or ora che potrei anche ottenermi tutti i
token dalla stringa spezzandola con split() e delimitatore lo spazio,
e poi controllarmi i token uno ad uno... un pò bruttino!
Faccio altri test con le precedenti che mi avete suggerito intanto.
Se vi viene in mente ottimizzazioni magari :-)
grazie ciao!

 deve essere FALSE.
scusa ma quella che ti ho postato fa esattamento questo, poi vedi tu
se deve tornare false o true, l'importante che faccia il match, infine
ripeto, devi solo prependere e postpendere uno spazio nella frase che
controlli.
d

 controlli.
si, scusami, le tue parole non mi erano sfuggite, stavo solamente
pensando "ad alta voce" :-)
per ora va benone "l'arteficio degli spazi" ;-)
eventuali ottimizzazioni se mi vengono o se vi vengono in mente
postiamoli qui magari :-)
mi piacerebbe capire, anche per curiosità a questo punto, se esiste
una souzione che "becca tutto in un colpo solo" :-)
grazie

caratteri.
Aaaah, allora avevo capito malissimo io. E' corretta la soluzione di
darko.
Pero', non ti puoi lamentare se (tranne col trucco degli spazi!) non
ti trova i token.
Hai detto ora che devono essere "separati da spazi", e nella stringa
"++ Scuola", "++" non e' delimitato da spazi, ma da uno spazio solo,
sulla destra :-)
Eventualmente usa esplicitamente (e' anche un tantino piu' rapido)
	preg_match(" (\+|\*|\&)+ ", " $string ");
se veramente con "spazio" intendi "spazio". Per i whitespace, rimane
la soluzione di darko.
Meglio di cosi' non credo che sia possibile fare.
In alternativa, se costa poco, puoi mettere il controllo di errore a
valle, quando presumibilmente estrai la parola ("scuola") ed i token
"vuoti" ti ritornano picche. Rallenta l'esecuzione ma, magari, cosi'
il codice e' un pochino piu' leggibile... non so se vale la candela,
pero'.


 pero'.
ti ringrazio! :)

 il codice e' un pochino piu' leggibile... non so se vale la candela,
a me la soluzione che hai proposto:
preg_match(" (\+|\*|\&)+ ", " $string ");
cioè con gli spazi dentro la preg_match mi sembra ancora più perfetta
ed elegante e sicuramente più leggibile rispetto ad estrarre i token,
parsarli, ecc.. mi sembrerebbe stupido scrivere altre righe di codice,
cicli, funzioni, solo per non mettere quei due spazietti innocui.
d

cicli, funzioni, solo per non mettere quei due spazietti innocui.
Sicuramente, ma intendevo che questo (fermo restando che COMUNQUE non
so se valga la candela) ha senso, se lui GIA' fa tutto il resto delle
operazioni.
Cioe', immagino che la faccenda non si limiti a vedere se mancano dei
token irregolari tipo " ++ " in "+scuola +privacy"; vorra' poi, spero
almeno, farci qualche cosa, con "scuola" e "privacy". Quando andra' a
farcelo, lo fara' (forse lo fa gia') con una estrazione di token come
"scuola" da "+scuola+". Questa estrazione fallira' con "++", dove nel
mezzo non c'e' niente.
Ecco, e fermo restando anche che cosi' si rallenta l'esecuzione, come
ho gia' messo le mani avanti (e una dietro :-) ), a questo punto puo'
o controllare PRIMA che non ci siano token illegali oppure aggiungere
un controllo DOPO per cui, se arriva un token vuoto, segnala errore.
E' chiaro che cosi' le cose rallentano (magari il token vuoto e' solo
in fondo a una stringa lunghissima), pero' cosi' l'errore e' visibile
nel flusso del codice - magari puo' fare cose tipo presentare a video
l'errore con dei suggerimenti o che so io... insomma: non dico che la
cosa ABBIA un senso, perche' potrebbe essere tutto un mio trip, ed in
questo thread credo sarebbe gia' il mio secondo o terzo :-); pero' in
certi casi POTREBBE anche avere senso.
(Sono un grosso fan del TMTOWTDI :-) )
Pero', se invece sta filtrando un file di righe di token per metterlo
da qui a la' ed elaborarlo poi, o cose cosi', allora il modo "rapido"
e' quello della tua regexp. Incidentalmente (e lo dico per chi avesse
letto l'altro mio messaggio) la tua e' la soluzione corretta al guaio
dei simboli ripetuti: (simbolo1\|simbolo2\|...)+. La mia con le "back
reference" FORSE funzionava anche, ma anche nel caso, era inutilmente
complessa.


 (Sono un grosso fan del TMTOWTDI :-) )
ah si si, questo pure io! :D
d

 > (Sono un grosso fan del TMTOWTDI :-) )
che significa? :)

che significa? :)
Googla ;-)
Okay, vuol dire "There's More Than One Way To Do It": "Si puo' fare in
diversi modi".


 diversi modi".
right! :)