2014-04-28 10 views
7

wrócić zphp preg_match pozycję ostatniego meczu

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

to możliwe, aby wyszukać ciąg w odwrotnej kolejności? to znaczy. powrót pozycję ostatniego wystąpienia wzorca w temacie zbliżonym do strripos

czy muszę wrócić pozycję wszystkich meczów z preg_match_all i wykorzystać ostatni element $matches?

+1

Proszę jasno, *** mam to i muszę to wyjście ***, pomóż nam pomóc. –

Odpowiedz

16

PHP nie ma metody, która wyszukiwania regex ciąg od prawej do lewej (jak w .NET). Istnieje kilka możliwych sposobów rozwiązania to:

  • użyciu preg_match_all z PREG_SET_ORDER flagi i end($matches) daje ostatni mecz ustawiony
  • odwrócenie ciąg z strrev i budowanie „odwrócone” wzorzec, który służy z preg_match
  • użyciu preg_match i budowanie wzór zakotwiczona na końcu łańcucha, który zapewnia nie ma więcej wystąpień poszukiwanego maski aż do końca łańcucha
  • użyć chciwy kwantyfikator przed i używać \K zacząć th e wynik meczu w wybranej pozycji. Po osiągnięciu końca łańcucha silnik regex cofa się, dopóki nie znajdzie dopasowania.

przykład z ciągiem $str = 'xxABC1xxxABC2xx' oraz dla wzoru /x[A-Z]+\d/

sposób 1:

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

sposób 2:

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

sposób 3:

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

sposób 3 (wariant):

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

sposób 4:

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

sposobem 4 (wariant): ograniczyć backtracking kroków, można załączyć ewentualne kawałki do grupy atomowej:

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

Poszedł z metodą pięści, nie wiem, czy jest jakiś niepotrzebny wydatek w zwrocie wszystkich meczów, ale działa dobrze – andrew

+1

Świetna odpowiedź sir. –

0

preg_match nie obsługuje wyszukiwania wstecznego, ponieważ nie jest to konieczne.

Możesz utworzyć wyrażenie regularne zawierające chciwą (to znaczy domyślną) stronę uprzedzającą, która pasuje do dowolnej pozycji (np. (?<=.*)stuff). W ten sposób powinieneś uzyskać ostatni występ swojego meczu.

szczegółowe informacje z oficjalnej dokumentacji tutaj: preg_match

+0

'(? <=. *)' Jest lookbehind i nieograniczona długość lookbehinds nie jest obsługiwana przez php. – stema

+0

poprawne, wymieszałem dwa imiona, przepraszam. Nie wiedziałem, że php tego nie obsługuje. – Jonny007

1

Nie rozumiem dokładnie tego, czego chcesz, ponieważ zależy to od tego, ile grup zostanie przechwyconych, wykonałem funkcję przechwytywania przesunięcia ostatniego układu przechwytywania do numeru grupy, we wzorze mam 3 grupy: pierwsza grupa, pełne przechwytywanie i dwie pozostałe grupy, podgrupy.

Wzór przykładowy kod:

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

przykładowy kod HTML:

$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>'; 

mojej funkcji, to rejestruje przesunięcie ostatniego elementu i masz możliwość wskazywania liczby dopasowywania:

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]; 
} 

Możesz uzyskać szczegółowe informacje na temat preg_match_all here na oficjalnej dokumentacji.

Korzystanie mój wzór na przykład:

0 => cały tekst
1 => href wartość
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(); 

wyjścia:

140 
149 
174 

My funkcja (tekst):

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]; 
} 

Przykładowy kod:

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>'; 

wyjściowa wynosi:

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

Dzięki za wgląd +1 – andrew

Powiązane problemy