Opreacje na tekscie. Wprowadzenie

Transkrypt

Opreacje na tekscie. Wprowadzenie
Technika
Operacje na tekście
Wprowadzenie
Operacje na tekście w locie są bardzo często potrzebne na naszych stronach
WWW. W innych językach programowania służą nam do tego zazwyczaj
standardowe funkcje jakiejś biblioteki. PHP ma ogromny zasób wbudowanych
funkcji, dzięki którym zrobimy z tekstem, co tylko chcemy.
Dowiesz się...
Powinieneś wiedzieć...
• Jak dzielić fragmenty tekstu.
• Jak usunąć niepotrzebne litery/ciągi, na podstawie danych kryteriów.
• Jak przeszukiwać tekst.
• Jak sprawdzić czy w tekście istnieje dany ciąg
znaków.
• Jak zamienić znaki w tekście.
• Jak zmienić kodowanie tekstu za pomocą funkcji
• Należy znać podstawową składnię języka PHP.
• Należy wiedzieć, co to jest zmienna i warunki
w PHP.
• Skrypty PHP uruchamiamy na serwerze (może
być lokalny) z zainstalowanym PHP.
• Należy wiedzieć, co to jest kodowanie strony
WWW.
Poziom trudności
P
o pierwsze, musimy wiedzieć, jak wygląda wyświetlanie tekstu w PHP. Wszelkie
operacje na tekście będziemy wykonywać
za pomocą funkcji na zmiennej, zawierający dany tekst. Powinno być oczywiste, że do wyświetlania tekstu w PHP służą funkcje echo i print. Są to
identyczne funkcje, więc dlaczego nie mogłaby być
tylko jedna? Dlatego, że w PHP wiele funkcji występuje np. pod dwoma nazwami, aby upodobnić się
do wielu języków programowania, by programistom było po prostu wygodniej nauczyć się PHP.
Mniejsza o to. Wyświetlmy testowo tekst „Ala ma
kota, a kot ma Alę” na kilka możliwości – Listing.1.
Wszystkie te zapisy są poprawne, a dla wyświetlania tekstu nie zawierającego żadnych zmiennych
najlepszym zapisem będzie ostatni – z użyciem zamknięcia i ponownego otwarcia kodu PHP między
tekstem. W tym przypadku nie jest używana żadna
funkcja PHP, gdyż tekst stanowi wtedy część dokumentu. Jest to zatem zapis najbardziej optymalny.
Oczywiście, do tekstu możemy także wprowadzić
zmienne. Dodajmy zmienną $cat z tekstem „kot” i
użyjmy ją w naszym kodzie. Dodajmy także zapis z
podwójnym cudzysłowiem ( “” ) – Listing 2. Przykład ten pokazuje, że w przypadku użycia pojedynczego cudzysłowia ( ' ' ) zmienne nie są parsowane
42
przez PHP, dlatego też musieliśmy tekst podzielić
na dwie części, a między nimi „dokleić” zawartość
zmiennej $cat. Jak widać, tekst łączy się znakiem
kropki. W piątej linijce naszego kodu zastosowano
skróconą wersję funkcji echo, za którą odpowiada
znak równości po pytajniku (<?=$cat?> wyświetla więc tekst „kot”). Ostatnie linijki pokazują, że w
przypadku użycia podwójnego cudzysłowia zmienne w nim zawarte są parsowane, jednak rozwiązanie to nie jest zalecane, gdyż wszystkie benchmarki PHP pokazują, że jest to sposób najwolniejszy.
W tekście wyświetlanym z pojedynczym cudzysłowem możemy bez problemu wstawić cudzysłów
podwójny, jednak aby wstawić pojedynczy, musimy poprzedzić go znakiem backslash ( \ ). Analogicznie wygląda sytuacja z użyciem wyświetlania
tekstu w podwójnym cudzysłowie, tyle że odwrotnie. Przykład:– Listing 3.Jak widać sytuacja ta nie
występuje, gdy wyświetlamy tekst bezpośrednio w
dokumencie. Zajmijmy się podstawową „obróbką”
tekstu. Najlepiej jest pracować z użyciem zmiennych. Zapisujemy więc nasze zdanie do zmiennej
$tekst. Jeśli nie mamy takiej możliwości (np. tekst
strony jest generowany przez PHP, a chcemy przerobić cały tekst wynikowy), możemy użyć bufora.
Wygląda to tak – Listing 4. Pierwsza funkcja, która
może nam się przydać, to substr. Pozwala ona na
skrócenie tekstu do określonej liczby liter. Ponadto
pozwala obciąć tekst nie tylko z jednej strony, ale i z
dwóch. Składnia funkcji wygląda tak:
substr(tekst, start, [długość]);
Pierwszy parametr to nasz tekst, podajemy
tam naszą zmienną. Drugi parametr określa,
od którego znaku tekst ma się zaczynać (np.
jeśli wstawimy 1 [liczenie od 0] to tekst zostanie ucięty do „la ma kota, a kot ma Alę”). Trzeci
parametr (długość) jest opcjonalny, jednak bardzo często używany, gdyż to on potrafi skrócić tekst. Przykład – Listing 5. Przydaje się to
często, jeśli np. tworzymy system newsów na
stronę i chcemy skrócić treść newsu na stronie
głównej do określonej ilości znaków. Przykładowo chcemy skrócić każdą wiadomość, która
ma treść dłuższą niż 200 znaków. Do sprawdzenia długości tekstu służy funkcja strlen.
Jej użycie jest proste – strlen(tekst). Zastosujemy prosty warunek skracający news. Załóżmy, że w zmiennej $news mamy treść newsa:
if (strlen($news) > 200) {
echo substr($news, 0, 200).'[...]';
}
else
{echo $news;
}
Jeśli news będzie dłuższy niż 200 znaków, zostanie skrócony właśnie do 200 znaków, a na jego
końcu zostanie dodany kwadratowy nawias z wielokropkiem. Możemy także z tekstu wyciągnąć jeden interesujący nas znak. Przydaje się to w różnych sytuacjach, np. jeśli chcemy zakodować jakąś
informację i wplatamy interesujące nas znaki pomiędzy znaki „śmieci", a nasz skrypt PHP będzie
te znaki wyciągał i układał w logiczną całość. Używamy w tym przypadku klamr przy zmiennej, a
między nimi podajemy konkretny indeks znaku.
Przykład takiego zastosowania:
$kod = 'fksmajso3jr0lf0es3a32fsgc';
$klucz = $kod{4}.$kod{12}.$kod{18};
echo $klucz;
Powyższy przykład wyświetli imię „ala”. Jak
widać, wszystko jest małymi literami – co
05/2007
Operacje na tekście
teraz zrobić, aby daną literę bądź całe słowo zamienić na wersaliki? Z pomocą przychodzi nam funkcja strtoupper oraz jej siostra strtolower, która zamienia litery na małe. Przykład zastosowania – Listing 6. Klamry możemy też wykorzystać do wyświetlania tekstu pionowo. W tym celu najlepiej
napisać własną funkcję. Nazwijmy ją po prostu “ustaw_tekst_pionowo”. Głównym środkiem użytym w naszej funkcji będzie pętla.
Funkcja najpierw policzy ile podany tekst
ma znaków, aby pętla mogła tyle razy przebiec i wyświetlać każdy znak z tagiem <br />
(przejście do następnej linii w HTML).
$n; $i++) {
}
}
echo $tekst{$i}.'<br />';
Jak widać zmienna-index $i jest ustawiana na 0, a zmienna $n przyjmuje wartość
długości zmiennej $tekst. Pętla wykonu-
je się dopóki warunek, iż $i jest mniejsze
od $n jest spełniony. Za każdym przebiegiem pętli zmienna $i zwiększana jest o 1.
Zastosować funkcję można bardzo łatwo
– ustaw _ tekst _ pionowo($zmienna) ub
bezpośrednio, np.
ustaw_tekst_pionowo('Mój tekst').
Listing 5. Zastosowanie funkcji substr
<?
$tekst = 'Ala ma kota, a kot ma Alę';
// Wyświetli “ ma kota, a kot ma “ - gdy obcinamy tekst z obu stron, należy
// w parametrze długość użyć znaku minus
function ustaw_tekst_pionowo($tekst)
{
for ($i = 0, $n = strlen($tekst); $i <
Listing 1. Kilka możliwości wyświetlenia
danego tekstu
<?
echo 'Ala ma kota, a kot ma Alę';
print 'Ala ma kota, a kot ma Alę';
?>Ala ma kota, a kot ma Alę<?
?>
echo substr($tekst, 3, -3);
?>
Listing 6. Przykład zastosowania funkcji strtoupper oraz strtolower
<?
$kod = 'fksmajso3jr0lf0es3a32fsgc';
$klucz = $kod{4}.$kod{12}.$kod{18};
echo strtoupper($klucz); // Wyświetli ALA
echo strtoupper($kod{4}).$kod{12}.$kod{18}; // Wyświetli Ala
echo strtolower(strtoupper($klucz)); // Wyświetli ala
?>
Listing 7. Przykład zastosowania funkcji strstr oraz stristr
Listing 2. Dodanie zmiennej $cat oraz
podwójnego cudzysłowia
<?
<?
// Zwróci “Wyraz 'ala' znajduje się w podanym tekście”
$tekst = 'Ala ma kota, a kot ma Alę';
$cat = 'kot';
if (stristr($tekst, 'ala')) {
print 'Ala ma kota, a '.$cat.' ma Alę';
} else {
echo “Ala ma kota, a $cat ma Alę”;
}
?>
if (strstr($tekst, 'ala')) {
Listing 3. Wyświetlanie tekstu w
podwójnym cudzysłowie
} else {
<?
}
echo “Ala ma 'kota', a \“kot\” ma Alę”;
if (strstr($tekst, 'Ala')) {
?>
} else {
Listing 4. Możemy użyć bufora
}
echo 'Ala ma kota, a '.$cat.' ma Alę';
?>Ala ma kota, a <?=$cat?> ma Alę<?
print “Ala ma kota, a $cat ma Alę”;
echo 'Ala ma \'kota\', a “kot” ma Alę';
?>Ala ma 'kota', a “kot” ma Alę<?
<?
// funkcja rozpoczynająca buforowanie
?>Wyraz 'ala' znajduje się w podanym tekście <?
?>Wyraz 'ala' nie znajduje się w podanym tekście <?
// Zwróci “Wyraz 'ala' nie znajduje się w podanym tekście” (małe litery)
?>Wyraz 'ala' znajduje się w podanym tekście<?
?>Wyraz 'ala' nie znajduje się w podanym tekście <?
// Zwróci “Wyraz 'Ala' znajduje się w podanym tekście”
?>Wyraz 'Ala' znajduje się w podanym tekście<?
?>Wyraz 'Ala' nie znajduje się w podanym tekście <?
?>
// Przykład użycia funkcji eregi i ereg
ob_start();
<?
/*
if (ereg('ala', $tekst)) { // Wyświetli "Nie znaleziono 'ala'"
tutaj wszystkie funkcje wyświetlające
tekst wynikowy
*/
// pobieranie już sparsowanego wyniku
// powyższych operacji do zmiennej
$tekst = 'Ala ma kota, a kot ma Alę';
?>Znaleziono 'ala'<?
} else {
}
?>Nie znaleziono 'ala'<?
if (eregi('ala', $tekst)) { // Wyświetli "Znaleziono 'ala'”
?>Znaleziono 'ala'<?
$tekst = ob_get_contents();
} else {
ob_end_clean();
}
// zamykanie i czyszczenie bufora
?>
www.phpsolmag.org
?>Nie znaleziono 'ala'<?
?>
43
Technika
Warunki na podstawie danego
tekstu
Jak sprawdzić, czy dany tekst zawiera podany
ciąg znaków? Możemy posłużyć się funkcjami
stristr i strstr. Funkcje robią to samo z tym
wyjątkiem, że stristr nie zwraca uwagi na
wielkość liter. Odpowiednikami tych funkcji są
także eregi i ereg z takim wyjątkiem, że funkcje mogą, aczkolwiek nie muszą, zostać użyte z wyrażeniami regularnymi ( np. aby określić konkretny zakres sprawdzania w danym
tekście, zamiast sprawdzać w całości). Funckja
eregi nie zwraca uwagi na wielkość liter.
Funkcji możemy użyć zatem tak – Listing 7.
Funkcje te można użyć także do wielu innych
rzeczy, np. do sprawdzania poprawności adresów e-mail podczas rejestracji użytkowników.
W artykule nie będziemy podawać przykładów,
które wymagają użycia dużo bardziej zaawansowanych wyrażeń regularnych. Funkcje te są zwykłymi funkcjami pozwalającymi na sprawdzenie
tylko „na sztywno” podanego ciągu znaku. Co
jednak, jeśli chcemy sprawdzić, czy w tekście
znajduje się jakikolwiek wyraz zaczynający się
np. na literę g, a kończący na literę a? Przykład
– nie znamy treści tekstu, chcemy wiedzieć, czy
zawiera słowo według podanych kryteriów, może to być np. gitara czy glazura. Z pomocą przyjdzie nam funkcja preg_match korzystająca z wyrażeń regularnych. Na temat wyrażeń regular-
Przeszukiwanie i zamiana tekstu
zaczynające się na g i kończące na a<?
PHP umożliwia także zamienianie pewnych
fragmentów tekstu na inne. Najczęściej używane, a zarazem najprostsze umożliwiające to
funkcje to str_replace i preg_replace. Składnia tych funkcji jest identyczna z tą różnicą, że
preg_replace używa wyrażeń regularnych,
dzięki czemu możemy tą funkcją zrobić więcej. Jednakże to ma też swoją wadę – funkcja
ta jest wolniejsza. Do zamiany stałych fragmentów tekstu dużo lepsza jest str_replace. Oto
jej składnia: str_replace(szukaj, zamień,
tekst);Funkcje te są bardzo proste w użyciu i
pozwalają na podanie im tablic do przeszukania i zamiany, co wpływa pozytywnie na wydajność (lepiej użyć raz funkcji z tablicą niż dziesięć razy osobno).Przykład – Listing 9. Funkcję
str_replace często wykorzystuje się także do
wycięcia danego fragmentu tekstu. Wtedy, jako
pierwszy parametr podajemy szukany ciąg, a jako drugi tylko pusty cudzysłów (''), np.
?>
str_replace('Ala ma kota', '', $tekst)
Listing 9. Przykłady użycia funkcji str_replace
spowoduje usunięcie wszystkich ciągów "Ala
ma kota" w zmiennej $tekst. Teraz bardziej
praktycznie rozwiązanie – przykładowo chcemy do wszystkich linków w danym tekście dodać klasę link, tak aby każdy link wyglądający
tak <a href=”...”>...</a> przyjął postać
Listing 8. Przykład użycia funkcji preg_match
<?
$tekst = 'Gitarzysta gra na gitarze. Jego gitara jest stara';
if (preg_match(“/\sg(.*?)a\s/s”, $tekst)) {
?>W podanym tekście występują wyrazy
zaczynające się na g i kończące na a<?
}
else {
?>W podanym tekście nie występują wyrazy
}
<?
$szukaj = 'kot';
$zamien = 'kocur';
$tekst = 'Ala ma kota, a kot ma Alę';
/*
Stosujemy funkcję str_replace bezpośrednio na zmiennej $tekst. Równie dobrze nie
musimy tego robić – wystarczy od razu wyświetlić funkcję (echo str_replace($szukaj,
$zamien, $tekst); )
*/
$tekst = str_replace($szukaj, $zamien, $tekst);
echo $tekst; // Wyświetli "Ala ma kocura, a kocur ma Alę"
?>
<?
// Przykład z użyciem tablic
<a href=”...” class=”link”>...</a>
– Listing 10.
W szablonie wyrażenia regularnego przy przeszukiwaniu każdy odnaleziony ciąg znaków
(wyrażenie (.*?) ) odpowiada kolejnej cyfrze po
dwóch znakach slash w zamianie (np. \1, \2).
$szukaj = array('kota', 'kot ');
Zmiana kodowania tekstu
za pomocą funkcji
$tekst = 'Ala ma kota, a kot ma Alę';
Często bywa tak, że mamy problem z kodowaniem znaków narodowych na naszych dynamicznych stronach. Na poprawne wyświetlanie takich
znaków na stronie wyświetlającej tekst z bazy
danych wpływa kodowanie bazy danych, kodowanie danej tabeli bazy danych, kodowanie pliku
wyświetlającego tekst oraz kodowanie samego
dokumentu HTML. Gdy jeden wariant jest niepoprawny, znaki nie zawsze wyświetlają się poprawnie (lub ich część). Ratować możemy się sami,
pisząc odpowiednią funkcję. Funkcja change_
encoding będzie zmieniała kodowanie danego
tekstu na podstawie znaków zawartych w tablicach (każdy znak ma swój kod, dlatego też funkcja
działa w każdym kodowaniu – Listing 11.
Funcja działa na prostej zasadzie – jako
pierwszy parametr podajemy tekst do przeko-
$zamien = array('koteczka', 'kocur ');
$tekst = str_replace($szukaj, $zamien, $tekst);
echo $tekst; // Wyświetli “Ala ma koteczka, a kocur ma Alę”
?>
Listing 10. Dodanie klasy link do wszyskich linków w tekście
<?
$linki = '<a href=”index.php”>Strona główna</a> <a href=”index.php?p=firma”>O firmie</a>
| <a href=”index.php?p=kontakt”>Kontakt</a>';
$linki = preg_replace(“#<a(.*?)href=\”(.*?)\”>(.*?)</a>#si”, '
<a\\1 href=”\\2” class=”link”>\\3</a>', $linki);
echo $linki;
// Przykład wyświetli “<a href=”index.php” class=”link”>Strona główna</a>
// | <a href=”index.php?p=firma” class=”link”>O firmie</a> <a href=
// ”index.php?p=kontakt” class=”link”>Kontakt</a>”
?>
44
nych nie będę się tu rozpisywał – jest to temat
rozległy i został opisany w numerze 6/2006 PHP
Solutions w artykule „Przyjazne URLe w PHP" .
Dlatego też w przykładzie zostało zapisane tylko
jedne potrzebne nam wyrażenie – Listing 8.
05/2007
Operacje na tekście
Listing 11. Tworzenie funkcji change_encoding
Listing 13. Użycie składni heredoc
<?
<?
$a = 5;
function change_encoding($string, $type)
{
$b = 'Ala ma kota';
$win2utf = array(
$c = 'a kot ma Alę';
$d = array('test1', 'test2');
"\xb9" => "\xc4\x85", "\xa5" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\
echo <<<EOT
xc4\x86", "\xea" => "\xc4\x99", "\xca" => "\xc4\x98",
“Witamy panie i panowie”
"\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81", "\xf3" => "\xc3\xb3", "\xd3" => "\
'To jest nasz test składni heredoc',
xc3\x93", "\x9c" => "\xc5\x9b", "\x8c" => "\xc5\x9a",
Teoretycznie nie ma tu ograniczeń.
"\xbf" => "\xc5\xbc", "\x8f" => "\xc5\xbb", "\x9f" => "\xc5\xba", "\xaf" => "\
3 + $a = 8.
xc5\xb9", "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83",
);
$b,$cMożemy także wyświetlać zawartości
$iso2utf = array(
?>
"\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81", "\xf3" => "\xc3\xb3", "\xd3" => "\
Listing 14. Przykład zastosowania znaków
specjalnych
"\xbc" => "\xc5\xba", "\xac" => "\xc5\xb9", "\xbf" => "\xc5\xbc", "\xaf" => "\
<?
xc4\x86", "\xea" => "\xc4\x99", "\xca" => "\xc4\x98",
xc3\x93", "\xb6" => "\xc5\x9b", "\xa6" => "\xc5\x9a",
$tekst = “Ten tekst\n przechodzi
xc5\xbb", "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83"
);
do\n nowej linii. Mam dużo
if ($type == 'ISO-8859-2->UTF-8') {
}
return strtr($string, $iso2utf);
/*
\$becho $tekst;
Przykład wyświetli:
else if ($type == 'UTF-8->ISO-8859-2') {
Ten tekst
}
nowej linii
return strtr($string, array_flip($iso2utf));
przechodzi do
else if ($type == 'WINDOWS-1250->UTF-8') {
}
Mam dużo $
return strtr($string, $win2utf);
*/
?>
else if ($type == 'UTF-8->WINDOWS-1250') {
}
return strtr($string, array_flip($win2utf));
else if ($type == 'ISO-8859-2->WINDOWS-1250') {
}
return strtr($string, "\xa1\xa6\xac\xb1\xb6\xbc", "\xa5\x8c\x8f\xb9\x9c\x9f");
else if ($type == 'WINDOWS-1250->ISO-8859-2') {
}
tablic, np. $d[0] EOT;
"\xb1" => "\xc4\x85", "\xa1" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\
}
return strtr($string, "\xa5\x8c\x8f\xb9\x9c\x9f", "\xa1\xa6\xac\xb1\xb6\xbc");
?>
Oto lista najczęściej używanych znaków specjalnych:
•
•
•
•
•
\n — nowa linia;
\r — powrót karetki;
\t — tabulacja pozioma;
\\ — odwrotny ukośnik;
\$ — znak dolara.
<?
Jak widać, znaki te zapisuje się poprzedzając
je backslashem. Przykład zastosowania – Listing 14.
$tekst = change_encoding($tekst, 'ISO-88592->WINDOWS-1250');
Podsumowanie
Listing 12. Zmiana kodowania
$tekst = 'Tekst z polskimi znakami ęóąśłżźćń zapisany w ISO-8859-2';
echo $tekst;
?>
dowania, a jako drugi typ kodowania. W zależności od tego jak kodowany jest tekst i jaki
chcemy otrzymać wynik, podajemy odpowiedni parametr. Do dyspozycji mamy zamianę
ISO-8859-2 na UTF-8 i odwrotnie, WINDOWS1250 na UTF-8 i odwrotnie oraz ISO-8859-2 na
WINDOWS-1250 i odwrotnie. Przykład użycia
funkcji – Listing 12.
Ciekawostki
Do zapisywania większej ilości tekstu wraz ze
zmiennymi i znakami specjalnymi bez obaw
o cudzysłowy możemy użyć składni heredoc.
Po funkcji echo lub print zamiast cudzysłowu
www.phpsolmag.org
otwieramy operator <<< po którym umieszczamy identyfikator składni (tym samym identyfikatorem należy zamknąć tekst). W przypadku prostszego tekstu posłuży nam identyfikator EOT. Przykład zastosowania – Listing 13.
Możemy także wyświetlać zawartości tablic.
Pamiętajmy o tym, że identyfikator kończący
tekst musi zaczynać się w pierwszej kolumnie
nowej linii, by nie spowodował błędu składni,
a po nim może znajdować się tylko średnik.
Warto wiedzieć, że wyświetlanie tekstu w
podwójnym cudzysłowie pozwala na używanie znaków specjalnych (cytowanych). Możemy zapisać przejście do nowej linii, akapit itp.
Przedstawione tu informacje o operacjach na tekście to tylko podstawy. Przy pomocy bardziej zaawansowanych funkcji oraz wyrażeń regularnych
możemy z tekstem robić dużo więcej. Mamy
nadzieję, że artykuł naprowadzi Cię na dalsze kroki w tej dziedzinie, która jest bardzo przydatna
w większości skryptów PHP.
MICHAŁ GACKI
Jest programistą-samoukiem. Od najmłodszych
lat interesuje się informatyką, a najbardziej
programowaniem, które jest jego pasją. Pracuje w założonej przez siebie grupie (obecnie nie
tylko programistycznej) pod nazwą Bil Software
(www.bilsoftware.com).
Kontakt z autorem: [email protected]
45