Autor | Zpráva | ||
---|---|---|---|
návštěvník Profil * |
#1 · Zasláno: 14. 1. 2014, 17:33:44
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. |
||
juriad Profil |
#2 · Zasláno: 14. 1. 2014, 17:43:57 · Upravil/a: juriad
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 |
#3 · Zasláno: 14. 1. 2014, 17:49:59
Raději mb_strrpos, ať jsou stejné ofsety před a po nahrazeních.
|
||
návštěvník Profil * |
#4 · Zasláno: 14. 1. 2014, 18:01:37
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>"; 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>"; |
||
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 * |
#6 · Zasláno: 14. 1. 2014, 18:15:31
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 * |
#8 · Zasláno: 14. 1. 2014, 18:58:01
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 * |
#10 · Zasláno: 14. 1. 2014, 19:42:14 · Upravil/a: návštěvník
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 * |
#12 · Zasláno: 14. 1. 2014, 20:05:58
juriad:
No já jsem s rozumem v koncích. Používám 5.2.1 takže offset by měl fungovat. |
||
abc Profil |
#13 · Zasláno: 14. 1. 2014, 20:12:47
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 * |
#14 · Zasláno: 14. 1. 2014, 20:36:49 · Upravil/a: návštěvník
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 * |
#16 · Zasláno: 14. 1. 2014, 21:55:21 · Upravil/a: návštěvník
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 * |
#17 · Zasláno: 15. 1. 2014, 12:39:01
/** 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 |
#18 · Zasláno: 15. 1. 2014, 14:31:29
Funkcí strrev lze text zrcadlově převrátit, pak použít strpos nebo mb_strpos a bude to defakto jako zprava doleva.
|
||
Časová prodleva: 11 let
|
0