A weblaboron merült fel egy kérdés: hogyan lehet szépen megoldani, hogy egy hosszú szövegből előállítsunk egy rövidebb bevezetőt, aminek korlátozva van a maximális hossza, és szóhatárnál végződik. Itt adok rá egy megoldást. Először is a megoldás: RegExp.

\A(.{0,60})\b

Ez a RegExp a következőt jelenti: vegyünk egy 0 és 60 karakter hosszú (rész)sztringet (.{0, 60}), amely az eredeti sztring elején kezdődik (\A) és szóhatárnál végződik (\b). A RegExp motor ezt többnyire elég gyorsan meg fogja találni, mivel mohón keresi, tehát a 60. karaktertől elindul visszafelé, és megkeresi a legelső karaktert, amely után szóhatár van (szóhatár alatt szó kezdetet és véget egyaránt értünk). Az első probléma ezzel, hogy szóközre (pontosabban white-space karakterre) végződő sztringet is kaphatunk (szó kezdet eset), úgyhogy ezt a kódból kezelnünk kell majd. Írjunk is köré egy wrappert:

<?php
function intro($string, $maxLength = 30, $template = '%1$s')
{
	if (preg_match(sprintf('/\A(.{0,%d})\b/si', $maxLength), $string, $result)) {
		return sprintf($template, rtrim($result[0]));
	}
	return '';
}

Végülis ennyi a függvény: dinamikusan beszúrjuk a kívánt maximális hosszt a fenti reguláris kifejezésbe, aztán ráeresztjük a sztringre, majd a kapott stringet behelyettesítjük a(z opcionálisan megadható) sablonba. Példa a használatára:

echo intro('Árvíztűrő tükörfúrógép, asdasd és foobar foo baz bar illetve lorem ipsum', 30, '%1$s ...');

És a kiemenet:


Árvíztűrő tükörfúrógép, asdasd ...
Harder

Harder

Profil

Korábbi hozzászólások (17)

A régi blogon érkezett hozzászólások archívuma. Új hozzászólást már nem lehet írni.

  1. crash

    a %l$s a templatenel mit jelent? ;]

  2. BlackY

    http://www.php.net/sprintf

    Az ott nem l (kis L), hanem 1 (egy, szám). Amúgy azt jelenti, hogy az első paraméter (1) sztringként (s) kerüljön oda.

    BlackY

  3. Tódi

    Sziasztok!

    És mit kellene akkor csinálni, ha ez a szöveg tele van formázásokkal?
    Hogy tudnám a html-t text-é alakítani?

    Köszönjük ezt a kis script-et :)

  4. BlackY

    Erre tökéletesen bevált recept nincs (mármint a markup-mentesítésre), viszont bevezetőt főleg olyan dolgokhoz szokás csinálni, amit admin felületen raksz fel és nem a userek küldenek be, egy strip_tags bőven elég (ha meg usertől származik az adat, amiről készül a bevezető, akkor keresel google-vel egy "remove html regexp"-et és kapsz pár találatot).

    Így a teljes hívás:

    $szoveg = 'asdasdfoobar';
    intro(strip_tags($szoveg), 30, '%1$s');

    BlackY

  5. Whiteford

    Én ezt a függvény használom a html formázások eltávolítására:

    function html2text($dokumentum) {
    $mit = array ("'<script[^.*?'si",
    "'<[\/\!]*?[^]*?>'si",
    "'([\r\n])[\s]+'",
    "'&(quot|#34);'i",
    "'&(amp|#38);'i",
    "'&(lt|#60);'i",
    "'&(gt|#62);'i",
    "'&(nbsp|#160);'i",
    "'&(iexcl|#161);'i",
    "'&(cent|#162);'i",
    "'&(pound|#163);'i",
    "'&(copy|#169);'i",
    "'&#(\d+);'e");

    $mire = array ("",
    "",
    " ",
    "\"",
    "&",
    "",
    " ",
    chr(161),
    chr(162),
    chr(163),
    chr(169),
    "chr(\\1)");
    return htmlspecialchars(preg_replace ($mit, $mire, $dokumentum));
    }

  6. cyruswww.cyrusmagus.hu

    Köszönjük eme függvényt, pofás és kicsi. Teljesen jól használható, ajánlom mindenki figyelmébe.

  7. lnorby

    Blacky! Ennek meg tudnád írni az Unicode karaktereket is támogató verzióját?

  8. BlackY

    Ha a preg_match-nél beadod még az u kapcsolót (tehát a vége /si helyett /usi), akkor már azzal is működni fog.

    BlackY

  9. lnorby

    Úgy próbáltam én is, de nem működött. Az unicode karakternél vette a szó végét és ott vágta el, meg hasonlók. Próbáld ki!

  10. BlackY

    És tényleg...
    Viszont ha a \b (szóhatárt) lecseréled egy (\s|\Z) (whitespace karakter vagy sor/input vége), akkor ugyanazt a működést kéne kapnod. Cserébe ezzel vannak csúnya esetek, amik a sima szóhatárnál nincsenek:

    Pl.: ha írásjelre végződik a kapott rész, akkor hülyén néz ki, hogy a levágott szöveged ilyen: "Árvíztűrő tükörfúrógép,", pont-kérdőjel-felkiáltójelnél ez még jól is jönne, de így. A trim-be mondjuk fel lehetne venni a karaktereket, amik hülyén néznek ki egy bevezető szöveg végén, csak szép hosszú lenne a lista.

    Azt lehetne csinálni, hogy a . helyett felsorolod a magyar betűket, a \b-t lecseréled egy negative lookahead-re (^([A-Záéűúőóüö]{0,30})(?![A-Záéűúőóüö])), az viszont nem csúnyán néz ki.

    BlackY

  11. szabofefamily-team.emszinet.hu

    Egy kicsit módosítva...

  12. szabofefamily-team.emszinet.hu

    Kicsit módosítva...
    ************************************
    function intro($string, $maxLength = 30, $template = '%1$s')
    { //formázás kivétele a szövegből
    $string = strip_tags($string);
    //módosított reguláris kifejezés
    $format='/\A(.{0,%d})[\s]\b/siu';
    if (preg_match(sprintf($format, $maxLength), $string, $result)) {
    //if (preg_match(sprintf('/\A(.{0,%d})\b/si', $maxLength), $string, $result)) {
    return sprintf($template, rtrim($result[0]));
    }
    return '';
    }
    *************************

További 5 hozzászólás-szál megjelenítése
  1. lnorby

    function strcut($text,$length,$dots=true)
    {
    if (preg_match('/^(.{0,' . $length . '})(?:,|;|\.|\?|!|\s|$)/su',$text,$matches)) return $matches[1] . ($dots && strlen($matches[1])<strlen($text) ? ' ...' : '');
    else return;
    }

  2. Tibi

    Nekem "lnorby" megoldása tökéletesen működik, viszont a vesszőre (,) vegződő vágott sztringeket elég csúnyán jeleníti meg (asdasd,...), s egyenlőre nem találtam rá megoldást (sajnos annyire nem értek még a Regexhez). :( Van esetleg valami ötlet?

  3. szabofefamily-team.emszinet.hu

    És így?
    function strcut($string,$maxLength,$dots=true)
    {
    if(preg_match('/^(.{0,' . $maxLength . '})(?:,|;|\.|\?|!|\s|$)/su',$string,$matches))
    //return $matches[1] . ($dots && strlen($matches[1])<strlen($string) ? ' …' : '');
    return str_replace(",", "", $matches[1]).($dots && strlen($matches[1])<strlen($string) ? ' …' : '');
    else
    return;
    }

  4. szabofefamily-team.emszinet.hu

    Ha csak az utolsót(a pontok előttit), akkor
    return substr_replace($matches[1], '', strlen($matches[1])-1, 1).($dots && strlen($matches[1])<strlen($string) ? '...' : '');

  5. Tibi

    Mit szólsz az "rtrim"-hez? (Igen, csak a pontok előtti vessző nem kell...)

    return rtrim($matches[1], ',') . ($dots && strlen($matches[1])<strlen($text) ? '...' : '');

Van hozzáfűznivalód? Írj nekem közvetlenül.

Kapcsolat