2014-04-28 18 views
7

di ritorno conphp preg_match la posizione dell'ultima partita

preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE); 

è possibile ricercare una stringa in senso inverso? vale a dire. restituire la posizione dell'ultima occorrenza del modello in oggetto simile a strripos

o devo per restituire la posizione di tutte le partite con preg_match_all e utilizzare l'ultimo elemento di $matches?

+1

Si prega di indicare chiaramente, *** HO QUESTO E ho bisogno di questa uscita ***, aiutaci ad aiutarvi. –

risposta

16

PHP non dispone di un metodo di espressione regolare che ricerca una stringa da destra a sinistra (come in .net). Ci sono diversi modi possibili per risolvere che:

  • usando preg_match_all con PREG_SET_ORDER bandiera e end($matches) vi darà l'ultima partita impostata
  • invertire la stringa con strrev e la costruzione di un "invertito" modello che si utilizza con preg_match
  • utilizzando preg_match e la costruzione di un modello ancorato al termine della stringa che assicura non c'è più occorrenze della maschera cercato fino alla fine della stringa
  • utilizzano un quantificatore avido prima e usano \K iniziare th e corrisponde il risultato nella posizione desiderata. Una volta raggiunta la fine della stringa, il motore regex tornerà indietro fino a trovare una corrispondenza.

esempio con la stringa $str = 'xxABC1xxxABC2xx' e per il modello /x[A-Z]+\d/

modo 1:

preg_match_all('/x[A-Z]+\d/', $str, $matches, PREG_SET_ORDER); 
print_r(end($matches)); 

modo 2:

if (preg_match('/\d[A-Z]+x/', strrev($str), $match)) 
    print_r(strrev($match[0])); 

modo 3:

preg_match('/x[A-Z]+\d(?=(?:(?!x[A-Z]+\d).)*$)/', $str, $match); 

modo 3 (variante):

preg_match('/x[A-Z]+\d(?!.*x[A-Z]+\d)/', $str, $match); 

modo 4:

preg_match('/^.*\Kx[A-Z]+\d/', $str, $match); 

modo 4 (variante): per limitare backtracking passaggi, è possibile racchiudere possibili pezzi in un gruppo atomico:

preg_match('/^(?>x[A-Z]+\d|[^x]+|x(?![A-Z]+\d))*\Kx[A-Z]+\d/', $str, $match); 
+0

Sono andato con il metodo del pugno, non so se ci sono alcune spese inutili nel restituire tutte le partite, ma funziona bene – andrew

+1

Grande risposta, signore. –

0

preg_match non supporta la ricerca inversa perché non è necessaria.

È possibile creare un file RegExp che contenga un avido (di default) lookahead che corrisponde a qualsiasi cosa (come (?<=.*)stuff). In questo modo dovresti ottenere l'ultima occorrenza della tua partita.

informazioni dettagliate da documentazione ufficiale qui: preg_match

+0

'(? <=. *)' È un lookbehind e le schermate di lunghezza illimitate non sono supportate da php. – stema

+0

corretto, ho mescolato i due nomi, mi dispiace. Non ero a conoscenza del fatto che php non lo supporta. – Jonny007

1

Non ho capito esattamente quello che vuoi, perché dipende da quanti gruppi verranno catturati, ho fatto una funzione per catturare l'offset dell'ultimo accordo di cattura al mio gruppo, nel mio modello, abbiamo 3 gruppi: il primo gruppo, la cattura completa e gli altri due gruppi, i sottogruppi.

modello codice di esempio:

$pattern = "/<a[^\x3e]{0,}href=\x22([^\x22]*)\x22>([^\x3c]*)<\/a>/"; 

codice HTML di esempio:

$subject = '<ul> 
<li>Search Engines</li> 
<li><a href="https://www.google.com/">Google</a></li> 
<li><a href="http://www.bing.com/">Bing</a></li> 
<li><a href="https://duckduckgo.com/">DuckDuckGo</a></li> 
</ul>'; 

mia funzione, si coglie l'offset dell'ultimo elemento e si ha la possibilità di indicare il numero di matching:

function get_offset_last_match($pattern, $subject, $number) { 
    if (preg_match_all($pattern, $subject, $matches, PREG_OFFSET_CAPTURE) == false) { 
     return false; 
    } 
    return $matches[$number][count($matches[0]) - 1][1]; 
} 

È possibile ottenere informazioni dettagliate su preg_match_all here sulla documentazione ufficiale.

Usando il mio modello, ad esempio:

0 => tutto il testo
1 => href valore
2 => innerHTML

echo '<pre>'; 
echo get_offset_last_match($pattern, $subject, 0) . PHP_EOL; // all text 
echo get_offset_last_match($pattern, $subject, 1) . PHP_EOL; // href value 
echo get_offset_last_match($pattern, $subject, 2) . PHP_EOL; // innerHTML 
echo '</pre>'; 
die(); 

uscita è:

140 
149 
174 

mio funzione (testo):

function get_text_last_match($pattern, $subject, $number) { 
    if (preg_match_all($pattern, $subject, $matches, PREG_OFFSET_CAPTURE) == false) { 
     return false; 
    } 
    return $matches[$number][count($matches[0]) - 1][0]; 
} 

codice di esempio:

echo '<textarea style="font-family: Consolas: font-size: 14px; height: 200px; tab-size: 4; width: 90%;">'; 
echo 'ALL = ' . get_text_last_match($pattern, $subject, 0) . PHP_EOL; // all text 
echo 'HREF = ' . get_text_last_match($pattern, $subject, 1) . PHP_EOL; // href value 
echo 'INNER = ' . get_text_last_match($pattern, $subject, 2) . PHP_EOL; // innerHTML 
echo '</textarea>'; 

uscita è:

ALL = <a href="https://duckduckgo.com/">DuckDuckGo</a> 
HREF = https://duckduckgo.com/ 
INNER = DuckDuckGo 
+0

Grazie per l'approfondimento +1 – andrew