2016-02-11 19 views
7

Ho cercato di ottenere l'espressione regolare per questo per tutta la mattina e ho colpito il muro. Nella stringa seguente non voglio corrispondere a ogni barra diretta che segue .com/<first_word> con l'eccezione di qualsiasi /dopo l'URL.Corrispondenza di un certo carattere dopo un Lookbehind positivo

$string = "http://example.com/foo/12/jacket Input/Output"; 
    match------------------------^--^ 

La lunghezza delle parole tra le barre non dovrebbe avere importanza.

Regex: (?<=.com\/\w)(\/) risultati:

$string = "http://example.com/foo/12/jacket Input/Output"; // no match 
$string = "http://example.com/f/12/jacket Input/Output"; 
    matches--------------------^ 

Regex: (?<=\/\w)(\/) risultati:

$string = "http://example.com/foo/20/jacket Input/O/utput"; // misses the /'s in the URL 
    matches----------------------------------------^ 
$string = "http://example.com/f/2/jacket Input/O/utput"; // don't want the match between Input/Output 
    matches--------------------^-^--------------^      

Poiché il lookbehind non può avere modificatori e deve essere un'asserzione di lunghezza zero mi chiedo se ho appena inciampato nel percorso sbagliato e dovrebbe cercare un'altra combinazione regex.

Il look positivo è il modo giusto per farlo? O mi manca qualcosa di diverso da una copiosa quantità di caffè?

NOTA: etichettato con PHP perché la regex dovrebbe funzionare in qualsiasi delle preg_* funzioni.

+2

funzione The'preg_match' restituisce uno partita. Dici che devi abbinare tutti i personaggi che ci sono dopo un certo schema. Dovresti usare 'preg_match_all'. –

+0

Ho ancora l'impressione che si tratti di un problema XY. Cosa stai cercando di ottenere? Perché abbinare quelle barre? Potresti url_parse dell'URL e poi fare ciò che vuoi. Esplodere, ad es. –

+0

No, non è un problema XY @ WiktorStribiżew come la regex dovrebbe funzionare in * any * delle funzioni 'preg_ *'. –

risposta

3

Se si desidera utilizzare preg_replace allora questo regex dovrebbe funzionare:

$re = '~(?:^.*?\.com/|(?<!^)\G)[^/\h]*\K/~'; 
$str = "http://example.com/foo/12/jacket Input/Output"; 
echo preg_replace($re, '|', $str); 
//=> http://example.com/foo|12|jacket Input/Output 

Così sostituendo ogni / da un | dopo la prima / visualizzato dopo l'avvio di .com.

È necessario uno sguardo negativo dietro (?<!^) per evitare di sostituire una stringa senza avviare .com come /foo/bar/baz/abcd.

RegEx Demo

+0

Il problema con questo è che sei sostituendo il '/' nella parte della stringa con 'Input/Output' –

+0

Dovrebbero essere solo le barre * dopo * foo, ma non in qualsiasi cosa non nell'URL –

+0

C'è un URL nella stringa, così come altri dati. Le barre negli altri dati non dovrebbero essere influenzate. –

3

Utilizzare \K qui insieme a \G .grab il groups.

^.*?\.com\/\w+\K|\G(\/)\w+\K 

Vedere la demo.

https://regex101.com/r/aT3kG2/6

$re = "/^.*?\\.com\\/\\w+\\K|\\G(\\/)\\w+\\K/m"; 
$str = "http://example.com/foo/12/jacket Input/Output"; 

preg_match_all($re, $str, $matches); 

Replace

$re = "/^.*?\\.com\\/\\w+\\K|\\G(\\/)\\w+\\K/m"; 
$str = "http://example.com/foo/12/jacket Input/Output"; 
$subst = "|"; 

$result = preg_replace($re, $subst, $str); 
+0

Per qualsiasi motivo questo non funzioni nel contesto di 'preg_match()' –

+0

OK - 'preg_match_all()' funziona ma altre funzioni 'preg ....' falliscono - come 'preg_replace()'. –

+0

@JayBlanchard l'unico problema con la sostituzione è una sostituzione in più alla fine .... suppongo che dovrà essere distribuito separatamente – vks