Autor Zpráva
návštěvník
Profil *
Jak řešit situaci, kdy potřebuju provést strpos ve směru zprava doleva? Existuje nějaká funkce? Fungovat by měla úplně stejně, vracet offset zleva, ale procházet řetězec by měla zprava. Proč to potřebuju: mám řetězec s diakritikou např.

Třistatřicet tři stříbrných stříkaček.
Chci nahradit v něm nahradit slova, které obsahují slovo tri/tři/tří za hvězdičky a tím se změní délka stringu. Jelikož ale porovnávám dva stringy, jeden s diakritikou a druhý bez diakritiky a mám v poli uložené informace o místech, kde se tyto stringy liší v pozici, záměnou za hvězdičky zleva:
1)
0123456789
Třistatřicet tři stříbrných stříkaček.
***statřicet tři stříbrných stříkaček.
Se změní pozice druhého nálezu "tři" z 7 na 6. Tím pádem by čísla uložené v mém poli neodpovídali těm správným hodnotám. Z toho vyplývá, že záměnu na hvězdičky bych potřeboval udělat zprava doleva. Ještě jednou, nejde mi o záměnu jako takovou, ale o zjištění pozice zprava doleva. Vyhnul bych se tím tomu problému se změnou pozic jednotlivých znaků.
juriad
Profil
V manuálu strpos v sekci See Also:
stripos() - Find the position of the first occurrence of a case-insensitive substring in a string
strrpos() - Find the position of the last occurrence of a substring in a string
strripos() - Find the position of the last occurrence of a case-insensitive substring in a string



Mimochodem, proč jsi opustil možnost řešení regulářními výrazy?
jak provést složitější záměnu pomocí regulárního výrazu
Tori
Profil
Raději mb_strrpos, ať jsou stejné ofsety před a po nahrazeních.
návštěvník
Profil *
juriad:
Myslím, že jsem sem chtěl vložit tento kód:
   // Vypiš pozice mezer odzadu
   $r = strrpos ( "Ahoj já jsem poslední. ", ' ',24);
   echo "$r<br>";
   $r = strrpos ( "Ahoj já jsem poslední. ", ' ',$r-1);
   echo "$r<br>";
   $r = strrpos ( "Ahoj já jsem poslední. ", ' ',$r-1);
   echo "$r<br>";
   $r = strrpos ( "Ahoj já jsem poslední. ", ' ',$r-1);
   echo "$r<br>";
funguje?

Tori:
   $r = mb_strrpos ( "Ahoj já jsem poslední. ", ' ',24,"utf8");
   echo "$r<br>";
   $r = mb_strrpos ( "Ahoj já jsem poslední. ", ' ',$r-1,"utf8");
   echo "$r<br>";
   $r = mb_strrpos ( "Ahoj já jsem poslední. ", ' ',$r-1,"utf8");
   echo "$r<br>";
   $r = mb_strrpos ( "Ahoj já jsem poslední. ", ' ',$r-1,"utf8");
   echo "$r<br>";
Funguje ti to? Mě ne
Tori
Profil
návštěvník:
K čemu vlastně (kromě nahrazení) potřebujete znát ty ofsety?
Jinak nefunguje, ofset (edit: tj. proměnná $r) by musel být záporný (= $r znaků od konce řetězce neprohledávat).
návštěvník
Profil *
Tori:
No, já právě chci ofset zleva ne zprava. Jestli tomu rozumím jak to myslíš?
Do detailů bych raději nezabíhal. Udělám asi vlastní funkci na porovnávání zprava. Snad to k něčemu bude.

juriad:
preg_replace_callback funguje bezvadně, ale to bylo na jiný úrovní, tam nešlo o text s diakritikou:
Tori
Profil
návštěvník:
já právě chci ofset zleva ne zprava. Jestli tomu rozumím jak to myslíš?
Ne ofset nalezený, ale ofset zadaný jako omezení pro strrpos (tady to je $ref):
$str = "Ahoj já jsem poslední. ";
$ln = mb_strlen($str, 'UTF-8');
$ref = 0;
while (($offset = mb_strrpos($str, ' ', $ref, 'UTF-8')) !== false) {
    echo "<br>nalezeno na pozici $offset, \$ref = $ref";
    $ref = ($ln - $offset + 1) * -1;
}
návštěvník
Profil *
Tori:
Tobě to funguje? To vypadá jako by se to zacyklovalo

nalezeno na pozici 22, $ref = 0
nalezeno na pozici 22, $ref = -2
nalezeno na pozici 22, $ref = -2 // a do nekončena ?
Tori
Profil
Jo, funguje.
nalezeno na pozici 22, $ref = 0
nalezeno na pozici 12, $ref = -2
nalezeno na pozici 7, $ref = -12
nalezeno na pozici 4, $ref = -17 // konec
návštěvník
Profil *
Tori:
nemám tušení proč, ale stále stejný problém. Vždycky se to zacykluje; několikrát jsem restartoval server.


všechny indicie ukazují že mě tato funkce prostě nefunguje. Toto ti funguje?

    $str = "Ahoj já jsem poslední. ";
    $ln = mb_strlen($str, 'UTF-8');
    $ref = 0;
    $offset = mb_strrpos($str, ' ', $ref, 'UTF-8');
    echo "<br>nalezeno na pozici $offset, \$ref = $ref";
    $ref = ($ln - $offset + 1) * -1;
    $offset = mb_strrpos($str, ' ', $ref, 'UTF-8');
    echo "<br>nalezeno na pozici $offset, \$ref = $ref";
    $ref = ($ln - $offset + 1) * -1;
    $offset = mb_strrpos($str, ' ', $ref, 'UTF-8');
    echo "<br>nalezeno na pozici $offset, \$ref = $ref";
    $ref = ($ln - $offset + 1) * -1;
    $offset = mb_strrpos($str, ' ', $ref, 'UTF-8');
    echo "<br>nalezeno na pozici $offset, \$ref = $ref";
    $ref = ($ln - $offset + 1) * -1;
juriad
Profil
návštěvník:
Ano, vypisuje:
<br>nalezeno na pozici 22, $ref = 0
<br>nalezeno na pozici 12, $ref = -2
<br>nalezeno na pozici 7, $ref = -12
<br>nalezeno na pozici 4, $ref = -17

PHP 5.5.8 (cli) (built: Jan 10 2014 15:34:09)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies
návštěvník
Profil *
juriad:
No já jsem s rozumem v koncích. Používám 5.2.1 takže offset by měl fungovat.
abc
Profil
návštěvník:
Nevím přesně proč, ale zdá se, že v PHP 5.2.0 - 5.2.3 to funguje maličko jinak...
http://3v4l.org/JqeMr#v520
návštěvník
Profil *
Nebylo by bezpečnější napsat si vlastní funkci místo mb_strrpos? Potřeboval bych aby mi to jelo jak na mém php tak na novějším.


Vlastně jsem myslel vlastní strrpos. mb asi nebudu potřebovat, kromě měření délky textu. Samotný řetězec needle nebude utf8.
Tori
Profil
Pokud byste fakt nechtěl použít ty reguláry, tak se dá využít i iconv_strlen a iconv_strrpos, akorát strrpos nebere parametr ofsetu, takže místo toho musíte zkopírovat řetězec do pomocné proměnné a postupně ho od konce osekávat (což je ještě víc nešikovné než tohle řešení).
návštěvník
Profil *
Tori:
Reguláry jsou zbytečné, pro tuto věc zbytečně náročné. Jakékoliv převody a práce s mb mi tu příjde úplně zbytečná. Začínám dělat na té funkci tak to sem pak pošlu.


Toto je pracovní verze ale zdá se že to funguje:
http://paste.ofcode.org/ngC9T9eRe2xxCUfVyKrfen
Kosmetické úpravy provedu zítra. Dík za konzultaci.
návštěvník
Profil *
/** use non utf8 needle like ' ,./ ' etc **/
function strbackpos($haystack, $needle, $offset=null){
 $c=0; $nl = strlen($needle); $hl = strlen($haystack);
 $begin=$offset==null?$hl-1:$offset;
 for ($h=$begin; $h>0; $h--)
   if ( $haystack[$h]==$needle[$nl-1] ):
     for ($n=$nl; $n>0; $n--):
       if ( $haystack[$h-$c]==$needle[$nl-1-$c] && ($c+1==$nl) ):
         return $h-$c;
       endif;
       $c++;
     endfor;
     return $h;
   endif;
return false;
} 

Jinak jsem ještě zkoušel variaci se static offset (static zůstane uložený uvnitř funkce). Ale asi to nemá moc velké využití:

/** use non utf8 needle like ' ,./ ' etc **/
function strbackposs($haystack, $needle, $o=0, $add=0){
 static $offset; 
 $c=0; $nl = strlen($needle); $hl = strlen($haystack);
 // $offset = isset($offset) ? $offset : ( $o > -1 ? $o : $hl-1 );
 $offset = $o > -1 ? ( isset($offset) ? $offset : $o ) :  $hl-1;
 
 echo "<b>static offset is $offset</b><br>";
 $begin=$offset==null?$hl-1:$offset;
 for ($h=$begin; $h>0; $h--)
   if ( $haystack[$h]==$needle[$nl-1] ):
     for ($n=$nl; $n>0; $n--):
       if ( $haystack[$h-$c]==$needle[$nl-1-$c] && ($c+1==$nl) ):
         $offset = $h-$c+$add;
         return $offset;
       endif;
       $c++;
     endfor;
     $offset = $h+$add;
     return $offset;
   endif;
return false;
}


          //01234578901234567890134
    $str = "Ahoj já jsem poslední/. ";
//    $offset = strlen($str)-1;
strbackposs($str, '/. ', $offset=-1);
// echo "<h3>result offset:$offset</h3>";

strbackposs($str, ' ', $offset, -1);
// echo "<h3>result offset:$offset</h3>";
$offset = strbackposs($str, ' ', $offset);
echo "<h3>result offset:$offset</h3>";

ECHO "ZNOVA</h3>";
strbackposs($str, '/. ', -1);
echo "<h3>result offset:$offset</h3>";

$offset = strbackposs($str, ' ', $offset, -1);
echo "<h3>result offset:$offset</h3>";
$offset = strbackposs($str, ' ', $offset);
echo "<h3>result offset:$offset</h3>";

Jde o to, že pokud bych nepotřeboval pracovat s $offset na vnější úrovni, tak to zůstane jen uvnitř; reset lokální proměnné offset se provádí pomocí arg2 = -1. arg3=-1 zajistí odečtení jedničky z výsledku offsetu, aby došlo k hledání následujícího needlu.
Chro
Profil
Funkcí strrev lze text zrcadlově převrátit, pak použít strpos nebo mb_strpos a bude to defakto jako zprava doleva.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: