• Strona główna
  • Curriculum Vitae
  • O mnie
  • Przykład: Gramatyka w PHP
  • Przykład: Kompresja CSS
  • Przykład: Kompresja JavaScript
  • Przykład: Skracanie linków
  • Przykład: Wykrywanie serwera HTTP
  • Przykład: Własna bramka SMS
  • Mapa strony
  • Kontakt
Niebieski Pomarańczowy Zielony Różowy Fioletowy

Gramatyka w PHP, część 1

Opublikowane 7 lutego 2010. Autor: Kamil Brenk. Wizyt: 4 290.

Kategorie: PHP
Tematyka: gramatyka i programowanie, PHP, programowanie strukturalne

lut 07

Chciałbym zaprezentować w tym wpisie krótką i prostą funkcję, która bywa bardzo użyteczna i jest wykorzystywana praktycznie w każdym moim projekcie.

Zgodnie z zasadami typografi, spójnik czy jedno-znakowy wyraz nie powinien być nigdy na końcu linii, lecz musi zostać przeniesiony do nowego wiersza/nowej linii.

Problem niby jest błahy i niezbyt istotny, jednak niektórzy są bardzo przewrażliwieni na punkcie poprawnej gramatyki, zwłaszcza w ojczystym języku. Poniżej zaprezentowana funkcja powinna rozwiązywać ten problem.

Kod źródłowy i opis działania
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/**
 * Upiększacz tekstu
 * zadaniem funkcji jest poprawienie tekstu na zgodny z zasadami języka polskiego
 *
 * @param string $text      tekst do poprawy
 * @param string $encoding  użyte kodowanie, domyślnie UTF-8
 * @return string           poprawiony tekst
 *
 * @authors Kamil Brenk <kontakt@kamilbrenk.pl>, Michal Wachowski
 * @license GPL
 * @link http://blog.kamilbrenk.pl/gramatyka-w-php-czesc-1/
 */


function repairText($text, $encoding  = 'UTF-8') {

    // poczatek tekstu jest poczatkiem zdania
    $uc_first = true;
   
    // --- ustalamy znacznik kropki wykorzystywany przy adresach email i WWW
    $dotItem = '#dot#';
    $dashItem = '#dash#';
   
    // konwertuj znaki specjalne do encji HTML
    $text = htmlspecialchars($text, ENT_NOQUOTES);
   
    // wywal podwójne i niepotrzebne spacje
    // wywal nadmiar wykrzykników, pytajników, przecinków, dwukropków, średników
    $text = preg_replace('/([?]){0,}([!]){0,}([,:;]){0,}([ ]){1,}/', '$1$2$3$4', $text);
   
    // --- zamieniamy kropki i myslniki na ustalone znaczniki w adresach e-mail, by reszta skryptu nie poprawila ich jako konce zdania itp.
    $text = preg_replace('/([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/ie', 'str_replace(array(".", "-"), array($dotItem, $dashItem), "$1")', $text);
   
    // --- zamieniamy kropki i myslniki na ustalone znaczniki w WWW, by reszta skryptu nie poprawila ich jako konce zdania itp.
    $text = preg_replace('/([A-Z0-9._%-]+\.[A-Z0-9.-]+\.[A-Z]{2,4}[A-Z0-9._%-\/?&=]*)/ie', 'str_replace(array(".", "-"), array($dotItem, $dashItem), "$1")', $text);
   
    // popraw zapis kropki i przecinka na prawidłowy w zdaniu
    // np. "wyraz. Wyraz", "wyraz, wyraz"
    // --- zmienilem zapis by rozróżniał wielokropek
    // --- pozbyłem się niepotrzebnych nawiasów () i {}
    // dodana poprawa: wykrzyknik, pytajnik, dwukropek, średnik
    $text = preg_replace('/(\pL+)[ ]*([.]{1,3}|[,;:]{1}|[!?]{1,2})[ ]*(\pL?)/', '$1$2 $3', $text);
   
    // popraw zapis myślnika na prawidłowy w zdaniu
    // np. "miasto - Bydgoszcz, państwo - Polska"
    // --- dodałem obsługę myślnika, wcześniej był tylko minus
    // --- jak wyżej - pozbyłem się niepotrzebnych nawiasów () i {}
    $text = preg_replace('/(\pL+)[ ]*-|–[ ]*(\pL?)/', '$1 - $2', $text);
   
    // stwórz z tekstu tablicę - każdy wyraz jako nowy rekord
    $text = explode(' ', trim($text));
   
    // przejdź przez tablicę wyrazów i popraw tekst
    foreach ($text as &$val) {
       
        // jeśli zaczynasz nowe zdanie - pisz wielką literą
        if ($uc_first) {
           
            // nowe zdanie rozpocznij wielką literą
            // --- dodałem parametr $encoding
            $val[0] = mb_strtoupper($val[0], $encoding);
           
            // koniec pierwszego wyrazu zdania
            $uc_first = false;
        }
       
        // jeśli wyraz zawiera kropkę - kończy zdanie
        // oznacz, że zaczyna się nowe zdanie
        // --- dodałem parametr $encoding
        // zdanie rozpoczynaj także po pytajniku i wykrzykniku
        if (
            mb_strpos($val, '.', 0, $encoding) !== false ||
            mb_strpos($val, '!', 0, $encoding) !== false ||
            mb_strpos($val, '?', 0, $encoding) !== false
        ) {
            $uc_first = true;
        }
       
        // jeśli długość wyrazu równa sie 1 - dodaj za nim twardą spację
        // jeśli wyraz jest kropką lub przecinkiem - pomiń
        // --- dodałem parametr encoding
        if (mb_strlen($val, $encoding) === 1) {
            $val = $val . '&nbsp;';
        }
       
        // niecodzienny przypadek, można pominąć
        // np. "wynik wynosi 2."
        // --- dodałem obsługę encoding
        if ( (mb_strlen($val, $encoding) === 2) && (($val[1] === ',') || ($val[1] === '.') || ($val[1] === '!')) ) {
            $val = $val . '&nbsp;';
        }
    }
   
    // ponownie połącz tekst
    $text = implode(' ', $text);
   
    // wywal normalne spacje po "twardych" spacjach
    // --- odmieniamy znaczniki kropki i myslnika w adresach e-mail i WWW na kropki i myslniki
    // zamień ?! na !?
    $text = str_replace(
                array('&nbsp; ', '?!', $dotItem, $dashItem),
                array('&nbsp;', '!?', '.', '-'),
            $text);
   
    // zwróć poprawiony tekst
    // --- kasujemy spacje z poczatku i konca tekstu, tak dla pewnosci
    // usuwamy twarde spacje z końca tekstu - niepotrzebne
    return trim($text, '&nbsp;');
   
}

Krótko opiszę zadania, które wykonuje powyższa funkcja.

  1. wywala niepotrzebne spacje – dopuszczalne są tylko pojedyncze spacje
  2. poprawa zapisu kropki i przecinku na prawidłowy, np. „wyraz. Wyraz”, „wyraz, wyraz”
  3. poprawa zapisu znaku myślnika, np. „miasto – Bydgoszcz, państwo – Polska”
  4. rozpoczynanie zdania wielką literą
  5. dodanie „twardych” spacji do jednoznakowych wyrazów i spójników
  6. dodanie „twardych” spacji do dwuznakowych wyrazów, jeśli jeden ze znaków jest przecinkiem, myślnikiem lub kropką
  7. usunięcie zbędnych spacji przed i za tekstem
  8. zamiana błędnego zapisu ?! na !?
  9. redukcja zbędnych wykrzykników, pytajników i innych znaków interpunkcyjnych oraz poprawa zapisu tych znaków,
  10. (czekam na kolejne propozycje)
Wykorzystanie

Do tak przygotowanej funkcji wystarczy przekazać tekst, który ma zostać poprawiony. Sam z niej korzystam najczęściej przy zapisie danych wysyłanych przez użytkowników: komentarzy, artykułów i innych, jak i danych wysyłanych przez siebie w panelu administracyjnym.

Gramatyka w PHP – pokaż przykład

Podsumowanie

Funkcja nie jest zbyt optymalna i wydajna, jednak używana z rozsądkiem może okazać się całkiem przydatna. Teraz tylko wystarczy testować i wytykać błędy – zapewne takowe się znajdą. Czekam również na kolejne propozycje rozbudowy funkcji :)

Komentarze (24)

  1. matiit 7 lutego 2010

    O, coś co każdy może wykorzystać.

  2. michal 9 lutego 2010

    Co stanie się w sytuacji gdy ktoś wprowadzi tekst bez odstępów po przecinkach/kropkach?
    (Już pomijam sens układania pojedynczych liter na początku tekstu, gdy zdania zaczynane są z małej litery)

    Moja wizja funkcji:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    function repairText($string, $encoding = 'utf-8') {
        $string = htmlspecialchars($string, ENT_NOQUOTES);
        $sArr = preg_split('#[,. ]#s', $string, NULL, PREG_SPLIT_OFFSET_CAPTURE);
       
        $ucFirst = true;
       
        foreach($sArr as &$elem) { 
            $pos = $elem[1] + strlen($elem[0]);
            $item = $string[$pos];
           
            if($ucFirst) {
                $ucFirst = false;
                $elem[0] = mb_substr(mb_strtoupper($elem[0], $encoding), 0, 1, $encoding).mb_substr($elem[0], 1, mb_strlen($elem[0], $encoding), $encoding);
            }
           
            if(strlen($elem[0]) == 1) {
                $elem[0] = $elem[0].'&nbsp;';
            }
           
            if($item == '.') {
                $ucFirst = true;
                $elem[0] = $elem[0].$item;
            }
           
            if($item == ',') {
                $elem[0] = $elem[0].$item;
            }

            $elem = $elem[0];  
        }
        $string = implode(' ', $sArr);
        $string = str_replace(array('&nbsp; ', ' ,', ' .'), array('&nbsp;', ',', '.'), $string);
        return $string;
    }

    Robi to co twoja propozycja + pierwsze słowo w zdaniu, z dużej litery, kropki i przecinki ‚przykleja’ do wcześniejszego wyrazu.

    (pewnie code nie działa?)

  3. Kamil Brenk 10 lutego 2010

    Dziękuję Michale za uwagę, Twoja funkcja faktycznie ma kolejne, lepsze poprawianie tekstu. Choć nie do końca mi działa, tzn.

    Input:
    ” zadaniem tego narzędzia jest upiększenie tekstu, tak by był zgodny z zasadami języka polskiego. obecnie jedyną obsługiwaną funkcją jest przeniesienie jedno-znakowego wyrazu (i, o, a) do następnego wiersza. ”

    output:
    ” Zadaniem tego narzędzia jest upiększenie tekstu,  tak by był zgodny z zasadami języka polskiego.  obecnie jedyną obsługiwaną funkcją jest przeniesienie jedno-znakowego wyrazu (i,  o ,  a) do następnego wiersza. ”

    Twoja funkcja tworzy podwójne spacje za kropkami i przecinkami, przez co pierwsza litera nowego zdania nie zawsze jest pisana wielką literą („obecnie”).

    Gdy tylko znajdę chwilę czasu postaram się ulepszyć funkcję, tzn.
    – zaaplikować proponowane przez Ciebie zmiany,
    – usuwać podwójne spacje z tekstu,
    – pozostawić poprzednią funkcjonalność.

    Sam blog też potrzebuje kilku poprawek i usprawnień (code w komentarzach i inne), ale to wkrótce.

    Tymczasem dziękuję za komentarz :)

  4. Michal Wachowski 10 lutego 2010

    To co wklejałem – powstało, niejako na szybko – zainspirowane Twoim rozwiązaniem.
    Osobiście nigdy nie porządkuję cudzych tekstów – pisząc niechlujnie, wystawia sam sobie wizytówkę.

    Wracając do funkcji – prócz wymienionego przez Ciebie błędów, zauważyłem jeszcze jeden – jeśli w tekście jest adres – zostanie on potraktowany jak ‚połączone zdanie’… to też trzeba by poprawić.

    Pisząc te funkcję – naszła mnie myśl, że prócz PHP’owej wersji – ciekawym rozwiązaniem była by wersja JS’owa.

  5. Kamil Brenk 12 lutego 2010

    Ok, naniosłem kilka proponowanych poprawek, rozszerzając swój przykład powyżej. Nie jest zbyt optymalnie i ładnie, trochę rozbudowana funkcja wyszła, ale trudno :)

    Co do JavaScript, ok – nie byłoby ciężko przepisać. Jednak przy jakim zdarzeniu tekst miałby być poprawiany? Myślę, ze byłoby to trochę denerwujące i mylące dla użytkownika, gdyby co chwile odświeżało mu pole tekstowe, nanosząc poprawki..

  6. Michal Wachowski 12 lutego 2010

    Użytkownik mógłby jakimś buttonem po napisaniu ‚upiększyć’ treść, ale to takie gdybanie – praktyka uczy, że i tak nikt tego nie będzie używał :D

    Wprowadzilem kilka dalszych poprawek i zagmatwań tj.:
    – dodałem do mb_* parametr $encoding
    – wywaliłem zbędną drugą tablicę
    – dodałem wyrażenia które podmieniają kropki i myślniki w adresach WWW i e-mail – przez co nie są one ‚poprawiane’
    – i kilka pomniejszych, estetycznych (na moje oko) poprawek w tym co już istnieje

    Większość rzeczy pokomentowałem, moje komentarze zaczynają się od // —

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    function repairText($text, $encoding  = 'UTF-8') {
        // poczatek tekstu jest poczatkiem zdania
        $uc_first = true;
       
        // --- ustalamy znacznik kropki wykorzystywany przy adresach email i WWW
        $dotItem = '#dot#';
        $dashItem = '#dash#';
       
        // konwertuj znaki specjalne do encji HTML
        $text = htmlspecialchars($text, ENT_NOQUOTES);
       
        // wywal podwójne i niepotrzebne spacje
        $text = preg_replace('/\s+/', ' ', $text);
       
        // --- zamieniamy kropki i myslniki na ustalone znaczniki w adresach e-mail, by reszta skryptu nie poprawila ich jako konce zdania itp.
        $text = preg_replace('/([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/ie', 'str_replace(array(".", "-"), array($dotItem, $dashItem), "$1")', $text);
       
        // --- zamieniamy kropki i myslniki na ustalone znaczniki w WWW, by reszta skryptu nie poprawila ich jako konce zdania itp.
        $text = preg_replace('/([A-Z0-9._%-]+\.[A-Z0-9.-]+\.[A-Z]{2,4}[A-Z0-9._%-\/?&=]+)/ie', 'str_replace(array(".", "-"), array($dotItem, $dashItem), "$1")', $text);
       
        // popraw zapis kropki i przecinka na prawidłowy w zdaniu
        // np. "wyraz. Wyraz", "wyraz, wyraz"
        // --- zmienilem zapis by rozróżniał wielokropek
        // --- pozbyłem się niepotrzebnych nawiasów () i {}
        $text = preg_replace('/(\pL+)[ ]*([.]{1,3}|[,]{1})[ ]*(\pL?)/', '$1$2 $3', $text);
       
        // popraw zapis myślnika na prawidłowy w zdaniu
        // np. "miasto - Bydgoszcz, państwo - Polska"
        // --- dodałem obsługę myślnika, wcześniej był tylko minus
        // --- jak wyżej - pozbyłem się niepotrzebnych nawiasów () i {}
        $text = preg_replace('/(\pL+)[ ]*-|–[ ]*(\pL?)/', '$1 - $2', $text);
       
        // stwórz z tekstu tablicę - każdy wyraz jako nowy rekord
        $text = explode(' ', trim($text));
       
        // przejdź przez tablicę wyrazów i popraw tekst
        foreach ($text as &$val) {
           
            // jeśli zaczynasz nowe zdanie - pisz wielką literą
            if ($uc_first) {
               
                // nowe zdanie rozpocznij wielką literą
                // --- dodałem parametr $encoding
                $val[0] = mb_strtoupper($val[0], $encoding);
               
                // koniec pierwszego wyrazu zdania
                $uc_first = false;
            }
           
            // jeśli wyraz zawiera kropkę - kończy zdanie
            // oznacz, że zaczyna się nowe zdanie
            // --- dodałem parametr $encoding
            if (mb_strpos($val, '.', 0, $encoding) !== false) {
                $uc_first = true;
            }
           
            // jeśli długość wyrazu równa sie 1 - dodaj za nim twardą spację
            // jeśli wyraz jest kropką lub przecinkiem - pomiń
            // --- usunąłem nawiasy, nie są potrzebne gdy są and'y
            // --- dodałem parametr encoding
            if (mb_strlen($val, $encoding) === 1 && $val !== '.' && $val !== ',' && $val !== '-') {
                $val = $val . '&nbsp;';
            }
           
            // niecodzienny przypadek, można pominąć
            // np. "wynik wynosi 2."
            // --- dodałem obsługę encoding
            if ( (mb_strlen($val, $encoding) === 2) && (($val[1] === ',') || ($val[1] === '.')) ) {
                $val = $val . '&nbsp;';
            }
        }
       
        // ponownie połącz tekst
        $text = implode(' ', $text);
       
        // wywal normalne spacje po "twardych" spacjach
        $text = str_replace('&nbsp; ', '&nbsp;', $text);
       
        // --- odmieniamy znaczniki kropki i myslnika w adresach e-mail i WWW na kropki i myslniki
        $text = str_replace(array($dotItem, $dashItem), array('.', '-'), $text);
       
        // zwróć poprawiony tekst
        // --- kasujemy spacje z poczatku i konca tekstu, tak dla pewnosci
        return trim($text);
    }

    Więcej się chyba nie da z tego wyciągnąć, kolejnym krokiem co by było? Sprawdzanie pisowni ? :)

  7. Kamil Brenk 13 lutego 2010

    Dziękuję Michale za pomoc, sam bym sobie nie poradził z wszystkimi powyższymi poprawkami :)

    Od siebie wprowadziłem kolejne dobre usprawnienia i poprawki, lecz sama funkcja niewiele się zmieniła. Choć funkcja jest stosunkowo kompletna, można by ją nadal rozwijać, m.in. wprowadzić prawidłową obsługę cudzysłów, nawiasów. Same poprawki mogą też czasami wprowadzać zamęt, m. in. w skrótach i akronimach (np. „m. in.”, „dr.” i inne).

    Powyższa funkcja może pomóc, ale może też trochę zaszkodzić :) Najlepiej chyba dać obok pola tekstowego przycisk typu „Popraw błędy i interpunkcję”, pokazać użytkownikowi proponowane zmiany – no i dać wybór zatwierdzenia lub odrzucenia poprawek :)

  8. Michal Wachowski 15 lutego 2010

    A proszę, proszę.
    (Po dr nie stawiamy kropki :D)

  9. PHP-owiec 16 marca 2010

    Hmm, …. zamiast całych tych super fajnych skryptów można użyć funkcji: ucwords() lub ucfirst().

  10. Kamil Brenk 20 marca 2010

    Hmm, …. zamiast całych tych super fajnych skryptów można użyć funkcji: ucwords() lub ucfirst().

    ucwords
    Powoduje zwiększenie KAŻDEGO wyrazu w zdaniu na zaczynającego się wielką literą.

    ucfirst
    Powoduje zamianę TYLKO pierwszego wyrazu zdania na pisaną wielką literą.

    Nie takie były założenia skryptu :-)

  11. Lolzer 31 maja 2010

    „zamiana błędnego zapisu ?! na !?”
    Oba zapisy są poprawne.
    http://so.pwn.pl/zasady.php?id=629840

    Kamil, skrót „m.in.” zapisujemy bez spacji pomiędzy, a „dr” w mianowniku bez kropki (w pozostałych przypadkach z kropką).

  12. Kamil Brenk 31 maja 2010

    Hehe, dziękuję za uwagę Lolzer ;)

    Domyślałem się, że za daleko popłynąłem z funkcjonalnością. Początkowym założeniem było dodawanie twardych spacji w miejscach, które to wymagają – co jest bardzo fajną i przydatną funkcjonalnością (stosowaną w praktyce w kilku innych serwisach, co bardzo się sprawdza i czego brakuje mi w WordPressie).

    Niestety w ramach bloga chciałem dopisywać kolejne „bajery” i powstał mały potworek, który dodatkowo nie jest zgodny z gramatyką i psuje prawidłowe zdania :D

  13. Lolzer 2 czerwca 2010

    Ja natomiast próbuję napisać coś, co usuwałoby niepotrzebne znaki np:
    ……………….. -> … (wiele kropek to pojedynczego wielokropka)
    .. – > . (2 kropki do jednej)
    ??????????????? -> ? (redukcja)
    !!!!!!!!!!!!!!!!!!!!!!!!!!! – ! (redukcja)
    ?!?!?!?!?! -> ?! (redukcja)
    !?!?!?!?!?!?! -> !? (redukcja)
    !!!!!!!!!!!!??!!!!!!!!!???!!!!!!!! -> !? (redukcja)
    !!!!!!!!!!!!!……….?????????? -> !? (usunięcie kropek za znakami interpunkcyjnymi; redukcja znaków)
    .! -> ! ale …! -> …! i ………! -> …! (przy wielokropku zostawiało bez zmian)
    .. .. . -> … (likwidacja spacji między kolidującymi znakami; redukcja)
    !… -> ! (usunięcie kropek/wielokropka za niektórymi znakami)
    „Pytanie?”. -> „Pytanie?” (usunięcie kropki za cudzysłowem, jeśli cytowane jest pytanie. To samo z wykrzyknikiem).
    „Zdanie.”. – > „Zdanie”. (usunięcie kropki w cudzysłowie, jeśli jest już jedna poza).
    (Wtrącenie.) -> (Wtrącenie). (przeniesienie ostatniej kropki poza nawias).
    „Zdanie.” -> „Zdanie”. (przeniesienie ostatniej kropki poza cudzysłów).
    Zdanie . -> Zdanie. (usunięcie spacji przed kropką, przecinkiem, średnikiem, pytajnikiem i wykrzyknikiem).
    I spacja zawsze po kropce i przecinku. Po wielokropku też, jeśli nie poprzedza znaku zapytania lub wykrzyknika.
    No i wstawianie twardych spacji w oczywistych przypadkach. Przyznaję, trochę mnie przerosło i mam wrażenie, że wyszedł mi mało optymalny kod, ponieważ zabieg musi być kilka razy powtórzony w pętli, gdyż przy redukcji niektórych niepotrzebnych znaków pojawia się kolizja innych, którą ponownie trzeba poddać redukcji.
    O linki i URL-e się nie boje, ponieważ są zakazane na mojej stronie.

  14. Lolzer 2 czerwca 2010
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?php

    function cleanThatShitUp($text){
    $text = preg_replace('#\.{1,}\)#i', ').' ,$text); //ostatnia kropka poza nawias
    $text = preg_replace('#\.{1,}"#i', '".' ,$text); //ostatnia kropka poza cudzysłów
    $text = preg_replace('/\s+/', ' ', $text);
    $text = preg_replace('# ([\.,\?!;])#i', '\\1' ,$text); //usuwanie spacji przed niektórymi znakami
    $text = preg_replace('#([\?!;"\',])\\1{1,}#i','\\1',$text); //redukcja powtarzających się znaków
    $text = preg_replace('#(\.){3,}#i','..',$text); //tutaj wyjątkowo nieeleganckie rozwiązanie -  ograniczenie maksymalnej liczby kropek do 2
    $text = preg_replace('#(\.\.)#i','...',$text); //...po czym następuje zamiana 2 kopek na wielokropek
    $text = preg_replace('#([\?!,;])\.*#i','\\1',$text); //usuwanie kropek po znakach interpunkcyjnych
    $text = preg_replace('#(\?!|!\?)*(\?|!)?#i','\\1',$text); //redukcja naprzemiennie postawionych "?" i "!"
    $text = preg_replace('#([\?!,;\.])([^\p{P}\s])#i','\\1 \\2',$text); //postawienie spacji po znaku interpunkcyjnym, jeśli nie jest poprzedzony białym znakiem lub innym znakiem interpunkcyjnym
    return $text;
    }

    echo cleanThatShitUp("WTF ??????????????!!!!!!!!!!!!!!....      lol1.....lol2 lol3.lol4 lol5..lol6      ....?!?!?!?!?!?!?........... lol7.. . ?? "lololol8." ''  lol9 .. lol10................????????!!!!!!!!?!?!?!?!?!lol11 . lol12!?!?!?!");

    //efektem będzie:
    //WTF?! lol1... lol2 lol3. lol4 lol5... lol6...?! lol7... "lololol8". ' lol9... lol10...?! lol11. lol12!?

    ?>

    Napisałem coś takiego bez użycia pętli. Może nie jest idealne, ale chyba radzi sobie z najbardziej hardcorowymi przypadkami. Tak myślę…
    Tak poprawiony tekst można później przepuścić przez Twoją funkcję z drobnymi zmianami.

  15. lolkowski 3 czerwca 2010

    Do forum się to jednak nie nadaje – tnie bbcode i linki.

    Pozdrawiam

  16. Lolzer 8 czerwca 2010

    Wykorzystałem kod Kamila i swój, trochę zmodyfikowałem (w kodzie, który podał wcześniej są błędy!) i nie tnie żadnych linków. No i funkcji bbcode należy użyć po tej funkcji, nie przed.

  17. Kamil Brenk 8 czerwca 2010

    Prawda Lolzer, WordPress tnie mi zamienia mi niektóre znaki i robi ogólny syf. W wolnym czasie napiszę wtyczkę, która by coś z tym robiła. Niemniej jednak dziękuję za uwagę, to dobra motywacja :-)

  18. lolkowski 9 czerwca 2010

    Lolzer. jeśli powyższy skrypt zamieni Ci link

    z http://www.costam
    na
    Www. Costam

    to żebyś użył bbcode nawet dwa ni po tej funkcji to nie zmieni to faktu, że link w bbode i tak nie będzie działał.

    Pozdrawiam

  19. Kamil Brenk 9 czerwca 2010

    @lolkowski, wybacz, jednak myślałem, że ksywka lolkowski i lolzer należy do tej samej osoby :P później postaram się pomóc, na razie sesja egzaminacyjna i brak czasu.. :)

  20. Lolzer 11 czerwca 2010

    @lolkowski, napisałem, że nie tnie linków.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    function repairText($text, $encoding  = 'UTF-8') {
        $uc_first = true;
       
        $dotItem = '#dot#';
        $dashItem = '#dash#';
        $questionItem = '#quest#';
        $comaItem = '#coma#';
       
        $text = preg_replace('/([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/ie', 'str_replace(array(".", "-", "?", ","), array($dotItem, $dashItem, $questionItem, $comaItem), "$1$2 ")', $text);
       
        $text = preg_replace('#(http[s]?://)([A-Za-z0-9_%\-\.:@]*)([A-Za-z0-9\-]+)\.([A-Za-z0-9\._%\-/\?&=:]*)([^\?!\.,;\s])#ie', 'str_replace(array(".", "-", "?", ","), array($dotItem, $dashItem, $questionItem, $comaItem), "$1$2$3.$4$5 ")', $text);

    $text = preg_replace('#\.{1,}\)#i', ').' ,$text);
    $text = preg_replace('#\.{1,}"#i', '".' ,$text);
    $text = preg_replace('/\s+/', ' ', $text);
    $text = preg_replace('# ([\.,\?!;])#i', '\\1' ,$text);
    $text = preg_replace('#([\?!;"\', ])\\1{1,}#i','\\1',$text);
    $text = preg_replace('#(\.){3,}#i','..',$text);
    $text = preg_replace('#(\.\.)#i','...',$text);
    $text = preg_replace('#([\?!,;])\.*#i','\\1',$text);
    $text = preg_replace('#([^\.])(\.)([\?!,;])#i','\\1\\3',$text);
    $text = preg_replace('#(\?!|!\?){1,}(\?|!)?#i','\\1',$text);
    $text = preg_replace('/\s+/', ' ', $text);
    $text = preg_replace('#([\?!,;\.])([^\p{P}\s])#i','\\1 \\2',$text);

        $text = htmlspecialchars($text, ENT_NOQUOTES);

        $text = explode(' ', trim($text));
       
        foreach ($text as &$val) {
           
            if ($uc_first) {

                if(!ereg('(http[s]?://)([^ ])+', $val) && !ereg('([\p{P}])', $val[0]) && !ereg('([A-Za-z0-9\-_\.])@([A-Za-z0-9\-_\.)\.([A-Za-z]){2,4}', $val)){
                                $val[0] = mb_strtoupper($val[0]);
             
                if($uc_first = true){
                $uc_first = false;
                }
                }
               
            if(ereg('(http[s]?://)([^ ]){1,}', $val) || ereg('([A-Za-z0-9\-_\.])@([A-Za-z0-9\-_\.)\.([A-Za-z]){2,4}' , $val)){
               
                if(ereg('([\.,\?!; ])', substr($val, -1, 1))){
                $i = -1;
                while(ereg('([\.,\?!; ])', substr($val, $i, 1))){
                               
                                $i--;
                }
                $i++;
                                $val = substr($val, 0, $i)." ".substr($val, $i, $i*(-1));
                }
               
                }  
            }
           
            if (
                mb_strpos($val, '.', 0, $encoding) !== false ||
                mb_strpos($val, '!', 0, $encoding) !== false ||
                mb_strpos($val, '?', 0, $encoding) !== false
            ) {
                $uc_first = true;
            }

            if (mb_strlen($val, $encoding) === 1) {
                $val = $val . '&nbsp;';
            }
           
            if ( (mb_strlen($val, $encoding) === 2) && (($val[1] === ',') || ($val[1] === '.') || ($val[1] === '!')) ) {
                $val = $val . '&nbsp;';
            }
        }
       
        $text = implode(' ', $text);
       
       $text = str_replace(
                    array('&nbsp; ', $dotItem, $dashItem, $questionItem, $comaItem),
                    array('&nbsp;', '.', '-', '?', ','),
                $text);  
       
        return $text;
       
    }

    Komentarze usunąłem tylko w tym kodzie – u mnie na stronie zostały, ponieważ zachowałem w nich te części kodu, których użył Kamil, a mi były niepotrzebne.

    Kod brzydki, ale działa. :P

  21. buddy 20 października 2011

    Dobry tekst, przyda mi się to. Pozdrawiam autora.

  22. Wojciech Brzeziński 29 kwietnia 2012

    „Zgodnie z zasadami gramatyki, spójnik czy jednoznakowy wyraz nie powinien być nigdy na końcu linii, lecz musi zostać przeniesiony do nowego akapitu.”
    Zamieniłbym na:
    „Zgodnie z zasadami typografi, spójnik czy jedno-znakowy wyraz nie powinien być nigdy na końcu linii, lecz musi zostać przeniesiony do nowego wiersza/nowej linii.”

    W paru miejscach rzeczywiście przydałaby się taka funkcja, chociaż chyba lepiej po stronie klienta.
    Prezentowane na tej stronie kody źródłowe można kopiować i dowolnie modyfikować?

  23. Kamil Brenk 30 kwietnia 2012

    @Wojciech Brzeziński: tak, można wykorzystywać do woli / modyfikować wg własnego uznania :) fajnie jednak wiedzieć, że ktoś/gdzieś użył mojego kodu, sama satysfakcja z tego wynikająca jest wystarczającym motywem :)

    Po stronie klienta ma taką zaletę, że w przypadku popełnienia błędu w algorytmie późniejsze korekty będą łatwiejsze (możliwe) do wykonania. W przypadku przerzucenia na serwer (tak jak jest teraz) nie trzeba poprawek nanosić każdorazowo i u każdego z osobna (co może widocznie pogorszyć wydajność/płynność działania strony); można by kombinować z jakąś hybrydą, ale żeby zachować zalety obu rozwiązań najłatwiej byłoby trzymać teksty użytkowników w dwóch kolumnach (oryginalny tekst; poprawiony tekst).

  24. andrew 12 marca 2015

    Witaj. Ogólnie bardzo ciekawa no i co najważniejsze praktyczna i przydatna funkcja. Myślę jednak że warto by było dodać opcję formatowania/nieformatowania znaczników (np:

    1
    zawartość kodu

    ), obecnie całość stringu zawierającego jakieś znaczniki sypie się. Często dane na stronie zawierają różnego rodzaju znaczniki, i w tym momencie funkcja nie może być ze zrozumiałych względów zastosowana, a przydałaby się. Dobrym pomysłem byłoby też po dodaniu wspomnianej opcji sprawdzanie i ewentualnie domykanie błędnych znaczników (niestety jak wiadomo zdarza się to niekiedy przy ręcznym pisaniu). Pozdrawiam :-)



Kamil Brenk Blog

PHP, JavaScript, SQL, HTML

  • Informacje o blogu

    Kamil Brenk

    Blog o tworzeniu aplikacji na potrzeby sieci Web.

    Praktyczne przykłady, porady i sztuczki. PHP, SQL, AJAX, JavaScript, HTML i pochodne.

    Kanał RSS

    • Najnowsze
    • Komentarze
    • Popularne
    • Liczniki w CSS
    • Wyprzedaż książek o programowaniu!
    • Niestandardowy placeholder
    • JavaScript w modułach
    • Co dalej z blogiem?
    • Interaktywna mapa w HTML i CSS
    • Olsztyn: Jak wyseparować zawartość zassaną przez file_get_content?
    • ERMLAB: Od czegoś trzeba zacząć :) Wiele osób właśnie stawia na...
    • david: co nalezy wkleić na stronę aby plik ze stylami był ladowany...
    • krynicz: Nie jestem pewien czy dobrze to rozumiem: wpisujemy OG w...
    • yaro: Jak zmienić re_write znak "_" na "-"?
    • Piotr: stworzyłem prostą stronkę w PHP, czy jest możliwość aby...
    • MichalR: Super sprawa... bardzo przydatne.. dzieki i pozdrawiam..
    • Niestandardowe czcionki na stronie
    • Sposoby wczytywania JavaScript
    • Gramatyka w PHP, część 1
    • Umowa i zaliczka dla freelancera
    • Wysyłanie wiadomości SMS w PHP
    • Projekt aplikacji po stronie klienta
    • Własny mechanizm Feed
  • Szukajka
    Wpisz co chcesz wyszukać na stronie…
  • Kategorie
    • Apache
    • Freelancer
    • Front-end Development
    • HTML5 & CSS3
    • Inne
    • JavaScript
    • Książki
    • PHP
    • Po godzinach
    • Pozycjonowanie
    • Protokół HTTP
    • SQL
    • Wyrażenia regularne
  • Moje serwisy
    • Testy zawodowe
    • Miłość, uczucia i seks
  • Czytane blogi
    • Wojciech Sznapka
    • Wojciech Soczyński
    • Michał Wachowski
    • Tomasz Kowalczyk
    • Filip Górczyński
  • Strona główna
  • Curriculum Vitae
  • O mnie
  • Przykład: Gramatyka w PHP
  • Przykład: Kompresja CSS
  • Przykład: Kompresja JavaScript
  • Przykład: Skracanie linków
  • Przykład: Wykrywanie serwera HTTP
  • Przykład: Własna bramka SMS
  • Mapa strony
  • Kontakt

Kamil Brenk © 2010. All rights reserved.

Designed by FTL Wordpress Themes brought to you by Smashing Magazine.

Do góry ∧