Szöveg első N karakterének kinyerése reguláris kifejezéssel, php-val

Az előző bejegyzésemhez hasonló megoldást mutatok, csak most nem adott számú szót vág le a függvény egy szövegből, hanem karaktereket. Szintén állítható, hogy mi kerüljön a levágott szöveg végére, ha volt mit vágni. És szintén megadható, hogy unicode szövegként legyen-e értelmezve a megadott string. Itt mégis a lényegesebb paramétere a függvénynek a 3. paraméter. Ha egy szövegben pont egy szót kéne ketté vágni, nem biztos, hogy jól mutat. Vegyük példának azt a szöveget, hogy: „Mi ez a foszfor?”. Ennek az első 11 karakterét levágva fixen elég érdekes eredményt kapnánk, ami nem biztos, hogy megengedhető. A következő függvény harmadik paraméterével szabályozható, hogy a szövegben a félbevágott szavakat be kell-e fejezni, vagy esetleg el sem kell kezdeni. Netán nyugodtan meg lehet vágni bárhol. A megoldás most is reguláris kifejezésekkel működik, bár az mb_substr függvényt is használhattam volna.

Függvény

/**
 * Szöveg első N karakterének kinyerése
 *
 * @param int $n Hány karakter kell
 * @param string $str A string, amiből az első N karakter kell.
 * @param bool $wordwrapmod Ha null, akkor szavak közben is megvághatja  szöveget.
 *                                                      Ha true, akkor befejezi a szót, aminek a közepén vágna.
 *                                                      Ha false, akkor el sem kezdi a szót, aminek a közepén vágna.
 * @param bool $unicode Unicode karaktereket is értelmezzen.
 * @param string $more Tetszőleges szöveg, jelölés, ami akkor kerül az eredmény mögé,
 *                                              ha vágni kellett belőle.
 * @return string A levágott első N karakter
 */

function firstNChar($n, $str, $wordwrapmod = null, $unicode = true, $more = ' ...')
{
        $php53 = version_compare(PHP_VERSION, '5.3') >= 0;
        $w = $php53 ? '\w' : ($unicode ? '\p{L}\p{N}' : '\w');
        $W = $php53 ? '\W' :  '^'.$w;
        $x = $b = '';
        if ($wordwrapmod) {
                $x = '(?(?=['.$w.']+)['.$w.']+)';
        } else if (!is_null($wordwrapmod)) {
                $b = '(?=['.$W.']+)';
        }
        return preg_replace('~^(?>(.{0,'.(int)$n.'})'.$b.$x.').+$~is'.($unicode ? 'u' : ''), '$1'.$more, $str);
}

Példák

$nl = '<br />'.PHP_EOL;
echo firstNChar(10, "Ez egy szöveg").$nl;
echo firstNChar(10, "Ez egy szöveg", false).$nl;
echo firstNChar(10, "Ez egy szöveg", true).$nl;
echo firstNChar(10, "Ez egy szöveg", null, false).$nl;
echo firstNChar(10, "Ez egy szöveg", null, true, ' <a href="">&raquo;</a>').$nl;

Eredmény

Ez egy szö ...<br />
Ez egy ...<br />
Ez egy szöveg<br />
Ez egy sz� ...<br />
Ez egy szö <a href="">&raquo;</a><br />
Kategóriák: 
Megosztás/Mentés

Hozzászólások

Brown ügynök képe

Szia!

A blogbejegyzések első 500 karakterét szeretném megjeleníteni. A 3. példa megfelelő lenne, ha a bejegyzés nem tartalmazna paragrafus tageket. Ha 500 karakternél hosszabb egy bejegyzés akkor a paragrafus lezáró tag nem jelenik meg. Ezt próbáltam orvosolni ezzel a kóddal:

preg_match("/<\/p>/",substr(wordwrap($str, 0,500), -4) != '</p>') ? $more = "" : $more = "</p>";

Sajnos így akkor is beszúrja a lezáró taget, ha a bekezdés lezáró tagje mégis belefért. ( Mert a wordwrap nem veszi figyelembe a tageket).

Bármilyen megoldás érdekel. :)

Rimelek képe

Helló. A megoldásom csak egyszerű szövegekre alkalmas. Ha neked az első bekezdés első 500 karaktere kell, előbb az első bekezdés tartalmát kell regexp-pel megkeresned. És csak azt vágni. De ha abban is van más html, akkor megint bonyolultabb a dolgod. Így két lehetőséged van. Az egyik, hogy a htmlt teljesen kiszűröd, és csak azt rövidíted 500 karakteresre. Ezt a strip_tags függvénnyel tudod megtenni. A másik, hogy a bevezetőt külön tárolod.

Amit te próbáltál az több okból is hibás. Először is nem garancia, hogy az utolsó 4 karakter lesz a bekezdészáró. Másodszor ha már az utolsó karaktert karaktereket ellenőrzöd, nem kell preg_match. És ha használsz preg_match-t, akkor annak második paramétere nem logikai érték kell legyen, mint esetedben, hanem string.

Brown ügynök képe

Akkor marad az, hogy külön letárolom. Az nem befolyásolja az oldal betöltési sebességét. :)