Wyrażenia regularne kasuje znaki specjalne

0

Witajcie.
Mam taki kod php:

$words = ['mleko', 'masło'];
$words = explode(' ', $value); // create an array of words
            foreach($words as $word) { //iterate through words
                $word = preg_replace('/[^\w]/uis', '', $word);
                if (in_array(mb_strtolower($word), $allergens)) {
                    $return .= "<b>" . $word . "</b> ";
                } else {
                    $return .= $word . " ";
                }
            }

Powyższy kod działa poprawnie, jednak kasuje mi znaki typu: ,. (spacje, przecinki) itp.
Tzn dodaje tagi html i dla wyrazów, w stringu które znajdują się w $words.

W jaki sposób mogę to naprawić? :)

Chciałbym żeby podrobienie czcionek pozostało, ale nie kasowało mi innych znaków specjalnych

2
baracadus napisał(a):
$word = preg_replace('/[^\w]/uis', '', $word);

Powyższy kod działa poprawnie, jednak kasuje mi znaki typu: ,. (spacje, przecinki) itp.

Powyższy kod działa poprawnie i robi, co mu kazano robić.
[^\w] znaczy: wszystko co nie jest literą ani cyfrą, a później każesz to zamienić na ''.

1

@baracadus: No dobra, ale co Ty właściwie chcesz zrobić? Chcesz obtoczyć tagiem html <b>/<i> słowa w stringu, które znajdują się w $words? No to pierwsza rzecz która mi przychodzi na myśl, to jeśli chcesz zamienić tekst na html, to musisz również zamieć w nim znaki specjalne na encje HTML. Napisałem o tym artykuł dwa dni temu: Znaki specjalne w HTML

Dla przykładu, jeśli Twój kod działałby tak jak go zaprogramowałeś, to jak mu dam takie dane:

$allergens = ['mleko', 'masło'];
$value = "Mój produkt zawiera: mleko, mąkę, masło!";
// [...] Tutaj jakiś Twój kod

To spodziewam się że chciałbyś zwrócić coś takiego: Mój produkt zawiera: <b>mleko</b>, mąkę, <b>masło</b>! Czy mam rację?

Bo jeśli tak, to robisz to źle.

Dla przykładu:

$value = "Mój produkt kupiony w H&M zawiera: mleko <3zł>,  masło <4zł>!";

powinno zwrócić "Mój produkt kupiony w H&amp;M zawiera: <b>mleko &lt;3zł&gt;, <b>masło</b> &lt;4zł&gt;!". No bo skoro zamieniasz tekst na HTML, to musisz go zamienić poprawnie. Jeśli tego nie zrobisz, Twoja strona będzie podatna na XSS. No chyba że dasz sobie rękę uciąć że te dane składają się tylko z liter, cyfr przecinków i kropek (ja bym np nie zaprogramował tego bez zamiany encji).

Co do orginalnego pytania, czy słyszaleś o takim wyrażeniu jak \b w regaxpach? Wygląda jakbyś robił explode(' ', tylko po to żeby oddzielić od siebie słowa, tylko problem jest taki że taki explode() po spacji nie zadziała Ci np w przypadku "mleko, jajka". Musiałbyś napisać "mleko , jajka". Lepszym wyjściem będzie \b, możesz o nim poczytać tutaj: https://gist.github.com/romulodl/1412498

Korzystając z \b, mógłbyś napisać coś takiego

$allergens = ['mleko', 'masło'];
$input = "Mój produkt zawiera: mleko, mąkę, masło!";
foreach ($allergens as $allergen) {
    $input = preg_replace('/\b' . preg_quote($allergen) . '\b/i', '<b>$0</b>', $input); // użyłem i, case-insensitive
}
Mój produkt zawiera: <b>mleko</b>, mąkę, <b>masło</b>!

Ale strzeż się tego, bo jeśli w $input będą specjalne znaki HTML to masz atak XSS gwarantowany.

PS: Mógłbyś też użyć bilbioteki T-Regx stworzonej specjalnie do takich rzeczy

$input = Pattern::inject('\b@\b', [$allergen], 'i')->replace($input)->withReferences('<b>$0</b>');

1 użytkowników online, w tym zalogowanych: 0, gości: 1