----- 最后更新【2022-01-05】-----
本文目錄結(jié)構(gòu)預(yù)覽:
- 一罐脊、簡介
- 二遂赠、String 語法
1廷蓉、字符串的4種聲明方式:
2俱萍、存取和修改字符串中的字符:
3蔗彤、字符串類型轉(zhuǎn)換 - 三、常用函數(shù)
1鞭铆、獲取子字符串
2玫恳、字符串替換
3、查找子字符串的位置
4芙沥、修改字符串
5诲祸、字符串轉(zhuǎn)為數(shù)組
6、其它常用函數(shù) - 四而昨、經(jīng)典實(shí)例
- 五救氯、參考
一、簡介
在 PHP 中歌憨,一個(gè)字符串(String)就是由一系列的字符組成着憨,其中每個(gè)字符等同于1
個(gè)字節(jié)。這意味著 PHP 底層只能支持256
的字符集务嫡,因此不支持 Unicode 等其它字符集(就比如 UTF-8:每個(gè)字符需要占用1到4個(gè)字節(jié)甲抖,而1個(gè)中文字符的 UTF-8 編碼需要占用3個(gè)字節(jié))。
String 的實(shí)現(xiàn)方式是(一個(gè)由字節(jié)組成的)數(shù)組
再加上一個(gè)整數(shù)(指明緩沖區(qū)長度)
心铃∽佳瑁可以這樣理解,如字符串hello
去扣,它在 PHP 中的實(shí)現(xiàn)方式就是由一個(gè)數(shù)組['h','e','l','l','o']
和一個(gè)整數(shù)5
組成柱衔。所以,如果一個(gè)字符串中如果存在多字節(jié)字符
的話愉棱,那 PHP 就會(huì)把它拆分成開來儲(chǔ)存(如一個(gè) UTF-8 中文字符會(huì)被分為3個(gè)字節(jié)存儲(chǔ))唆铐。
實(shí)現(xiàn)方式清楚了,但是 PHP 并沒有如何將字節(jié)轉(zhuǎn)換成字符的信息奔滑,也就是沒有特別指明字符串使用的編碼方式艾岂。相反它是把這個(gè)交給程序員自己來決定了,程序員可以根據(jù)自己的需求档押,決定使用什么字符編碼澳盐。默認(rèn)情況下字符串會(huì)被按照該腳本文件相同的編碼方式來編碼祈纯,因此如果一個(gè)腳本的編碼是 ISO-8859-1,則其中的字符串也會(huì)被編碼為 ISO-8859-1叼耙。
理解以上的概念對熟悉使用 PHP 的 String 類型來說是非常重要的腕窥,因?yàn)橐粋€(gè) PHP 程序員其實(shí)大部分時(shí)間都是在和字符串打交道。(關(guān)于字符集和字符編碼的介紹可以查看本文末尾的參考部分)
二筛婉、String 語法
1簇爆、字符串的4種聲明方式:
在php語法當(dāng)中,一個(gè)字符串可以用 4 種方式表示爽撒,它們分別是:單引號(hào)
入蛆、雙引號(hào)
、heredoc語法結(jié)構(gòu)
硕勿、nowdoc語法結(jié)構(gòu)
哨毁。
1)單引號(hào)
要表達(dá)一個(gè)單引號(hào)自身,需在它的前面加個(gè)反斜線\
來轉(zhuǎn)義源武,即\'
扼褪。要表達(dá)一個(gè)反斜線自身,則用兩個(gè)反斜線\\
粱栖。其它任何方式的反斜線都會(huì)被當(dāng)成反斜線本身话浇,即在單引號(hào)字符串中的變量和特殊字符的轉(zhuǎn)義序列將不會(huì)被替換(例如\r
或者\n
也是不會(huì)被轉(zhuǎn)義,也是原樣輸出)闹究。
2)雙引號(hào)
如果字符串是包圍在雙引號(hào)" "
中幔崖, PHP 將對一些特殊的字符進(jìn)行解析。
當(dāng) PHP 解析器遇到一個(gè)美元符號(hào)$
時(shí)渣淤,它會(huì)和其它很多解析器一樣赏寇,去組合盡量多的標(biāo)識(shí)以形成一個(gè)合法的變量名砂代√6可以用花括號(hào){}
來明確變量名的界線刻伊。
常見的轉(zhuǎn)義字符:
轉(zhuǎn)義字符 | 含義 |
---|---|
\n | 換行(ASCII 字符集中的 LF 或 0x0A (10)) |
\r | 回車(ASCII 字符集中的 CR 或 0x0D (13)) |
\t | 水平制表符(ASCII 字符集中的 HT 或 0x09 (9)) |
\v | 垂直制表符(ASCII 字符集中的 VT 或 0x0B (11)) |
\e | Escape(ASCII 字符集中的 ESC 或 0x1B (27)) |
\f | 換頁(ASCII 字符集中的 FF 或 0x0C (12)) |
$name | PHP變量的值 |
\$ | 美元符號(hào)本身 |
\\ | 反斜線本身 |
\" | 雙引號(hào)本身 |
\[0-7]{1,3} | 符合該正則表達(dá)式序列的是一個(gè)以八進(jìn)制方式來表達(dá)的字符 |
\x[0-9A-Fa-f]{1,2} | 符合該正則表達(dá)式序列的是一個(gè)以十六進(jìn)制方式來表達(dá)的字符 |
\u{[0-9A-Fa-f]+} | 匹配正則表達(dá)式的字符序列是 unicode 碼位露戒, 該碼位能作為 UTF-8 的表達(dá)方式輸出字符串 |
3)heredoc 語法結(jié)構(gòu)
第三種表達(dá)字符串的方法是用 heredoc 語法結(jié)構(gòu):<<<
荠锭。在該運(yùn)算符之后要提供一個(gè)標(biāo)識(shí)符,然后換行著摔。接下來是字符串 string 本身,最后要用前面定義的標(biāo)識(shí)符作為結(jié)束標(biāo)志梨撞。
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
Warning: 要注意的是結(jié)束標(biāo)識(shí)符這行除了可能有一個(gè)分號(hào);
外雹洗,絕對不能包含其它字符。這意味著標(biāo)識(shí)符不能縮進(jìn)卧波,分號(hào)的前后也不能有任何空白或制表符。
4)nowdoc 語法結(jié)構(gòu)
就象 heredoc 結(jié)構(gòu)類似于雙引號(hào)字符串庇茫,Nowdoc 結(jié)構(gòu)是類似于單引號(hào)字符串的港粱。Nowdoc 結(jié)構(gòu)很像 heredoc 結(jié)構(gòu),但是 nowdoc 中不進(jìn)行解析操作旦签。這種結(jié)構(gòu)很適合用于嵌入 PHP 代碼或其它大段文本而無需對其中的特殊字符進(jìn)行轉(zhuǎn)義查坪。
一個(gè) nowdoc 結(jié)構(gòu)也用和 heredocs 結(jié)構(gòu)一樣的標(biāo)記<<<
, 但是跟在后面的標(biāo)識(shí)符要用單引號(hào)括起來宁炫,即<<<'EOT'
偿曙。Heredoc 結(jié)構(gòu)的所有規(guī)則也同樣適用于 nowdoc結(jié)構(gòu),尤其是結(jié)束標(biāo)識(shí)符的規(guī)則羔巢。
$str = <<<'EOD'
Example of string
spanning multiple lines
using nowdoc syntax.
EOD;
注意:
-- 單引號(hào)比雙引號(hào)效率更高望忆。
-- 當(dāng)雙引號(hào)里面包含單引號(hào),然后單引號(hào)里面包含變量竿秆,這種情況變量也是會(huì)正常解析的启摄,同時(shí)單引號(hào)會(huì)原樣輸出。
2幽钢、存取和修改字符串中的字符:
string 中的字符可以通過一個(gè)從 0
開始的下標(biāo)歉备,用類似 array 結(jié)構(gòu)中的方括號(hào)包含對應(yīng)的數(shù)字來訪問和修改,比如$str[4]
匪燕。也可用花括號(hào)訪問蕾羊,比如 $str{4}
喧笔。(從 PHP 7.4 起,訪問字符串的{}
大括號(hào)語法被棄用龟再,自 PHP 8.0.0 開始已移除书闸。)
php > $str = "Hi, I'm a.";
php > $str[8]='b';
php > echo $str;
Hi, I'm b.
注意!使用以上方法修改字符串的時(shí)候要特別小心吸申,因?yàn)?PHP 的字符串在內(nèi)部是由一個(gè)1字節(jié)
的值組成的數(shù)組(可以看作是Byte類型)梗劫,所以它在二進(jìn)制下的取值范圍為0~255
(例如ASCII、ISO-8859-1是單字節(jié)編碼截碴,所以它們不會(huì)有問題)梳侨。如果修改的值大于1字節(jié)
的話,那么可能會(huì)出現(xiàn)亂碼或者字符串丟失等問題日丹。
如:
php > $str = 'hello, Nosee!';
php > $str[0] = '我';
php > echo $str;
夬lo, Nosee!
php >
上面就出現(xiàn)了亂碼(以上腳本使用的是UTF-8編碼走哺,那么中文的我
字就需要3
個(gè)字節(jié)來表示,這就導(dǎo)致后面2
個(gè)字節(jié)的值會(huì)丟失哲虾,所以出現(xiàn)了亂碼)丙躏。
Tip:字符串可以用 '.
'(點(diǎn))運(yùn)算符連接起來,注意 '+
'(加號(hào))運(yùn)算符沒有這個(gè)功能束凑。
3晒旅、字符串類型轉(zhuǎn)換
1)自動(dòng)轉(zhuǎn)換
在一個(gè)需要字符串的表達(dá)式中,會(huì)自動(dòng)轉(zhuǎn)換為 string汪诉。比如在使用函數(shù) echo 或 print 時(shí)废恋,或在一個(gè)變量和一個(gè) string 進(jìn)行比較時(shí),也會(huì)發(fā)生這種轉(zhuǎn)換扒寄。
2)手動(dòng)轉(zhuǎn)換
一個(gè)值可以通過在其前面加上(string)
或用strval()
函數(shù)來轉(zhuǎn)變成字符串鱼鼓,也可參考函數(shù)settype()
,如settype($var, "string");
该编。
三迄本、常用函數(shù)
與字符串相關(guān)的常用方法,這里總結(jié)為以下六個(gè)大類:
1.獲取子字符串课竣、2.字符串替換嘉赎、3.查找子字符串的位置、4.修改字符串稠氮、5.字符串轉(zhuǎn)為數(shù)組曹阔、6.其它常用方法
1、獲取子字符串
方法 | 說明 |
---|---|
substr | 返回字符串中指定位置的子串 |
mb_substr | 根據(jù)字符數(shù)執(zhí)行一個(gè)多字節(jié)安全的 substr() 操作隔披。 |
strstr (別名: strchr) | 查找字符串的首次出現(xiàn)赃份,返回該位置到字符串末尾的部分 |
stristr | strstr函數(shù)的忽略大小寫版本 |
strrchr | 查找指定字符在字符串中的最后一次出現(xiàn),返回字符串到末尾的部分 |
preg_match | 執(zhí)行匹配正則表達(dá)式(在第一次匹配成功后,將會(huì)停止搜索) |
preg_match_all | 執(zhí)行一個(gè)全局正則表達(dá)式匹配 |
strpbrk | 在字符串中查找一組字符的任何一個(gè)字符 |
例1:substr—返回字符串的子串
string substr( string $string, int $start [, int $length ] )
返回字符串 string 由 start 和 length 參數(shù)指定的子字符串抓韩。
substr("abcdef", -3, 1); // 返回 "d"
substr('abcdef', 1, 3); // bcd
$a = '第二部分'; # 注意:一個(gè)漢字等于3個(gè)UTF_8字符
substr($a, 0, 3); // 返回 "第"
substr($a, 0, 4); // 返回 "第?"纠永,后面會(huì)多一個(gè)亂碼
例2:strstr—查找字符串的首次出現(xiàn);別名也叫strchr
string strstr ( string $haystack , mixed $needle [, bool $before_needle = FALSE ] )
返回 haystack 字符串從 needle 第一次出現(xiàn)的位置開始到 haystack 結(jié)尾的字符串
Note:如果你僅僅想確定needle是否存在于haystack中谒拴,請使用速度更快尝江、耗費(fèi)內(nèi)存更少的strpos()
函數(shù)。
$email = 'name@example.com';
echo strstr($email, '@'); // 打印 @example.com
echo strstr($email, '@', true); // 打印 name英上,從 PHP 5.3.0 起
2炭序、字符串替換
方法 | 說明 |
---|---|
substr_replace | 替換字符串指定位置的子串 |
str_replace | 子字符串替換(搜索替換) |
str_ireplace | str_replace 的忽略大小寫版本 |
strtoupper | 將字符串轉(zhuǎn)化為大寫 |
strtolower | 將字符串轉(zhuǎn)化為大寫 |
ucfirst | 將字符串的首字母轉(zhuǎn)換為大寫 |
ucwords | 將字符串中每個(gè)單詞的首字母轉(zhuǎn)換為大寫 |
lcfirst | 使一個(gè)字符串的第一個(gè)字符小寫 |
例1:substr_replace—替換字符串的子串
mixed substr_replace ( mixed $string , mixed $replacement , mixed $start [, mixed $length ] )
substr_replace() 在字符串 string 的副本中將由 start 和可選的 length 參數(shù)限定的子字符串使用 replacement 進(jìn)行替換。返回結(jié)果字符串苍日。如果 $string 是個(gè)數(shù)組惭聂,那么也將返回一個(gè)數(shù)組。
Tip: 在用于長文本隱藏時(shí)非常有用(如用...
來替換后面的字符串)相恃。
php > $str ='sdkfjhaskiufhasvcnaisuefhwaief';
php > echo substr_replace($str,'...',10);
sdkfjhaski...
例2:str_replace—子字符串替換(搜索替換)
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
該函數(shù)返回一個(gè)字符串或者數(shù)組辜纲。該字符串或數(shù)組是將 subject 中全部的 search 都被 replace 替換之后的結(jié)果。
如果沒有一些特殊的替換需求(比如正則表達(dá)式)拦耐,你應(yīng)該使用該函數(shù)替換 ereg_replace()
和 preg_replace()
耕腾。
php > $str = "Line 1,\nLine 2,\rLine3,\r\nLine 4";
php > $search = array("\r\n", "\n", "\r");
php > $replace = '<br />';
php > $newstr = str_replace($order, $replace, $str); //首先替換 \r\n 字符,因此它們不會(huì)被兩次轉(zhuǎn)換
php > echo $newstr;
Line 1,<br />Line 2,<br />Line3,<br />Line 4
3杀糯、查找子字符串的位置
方法 | 說明 |
---|---|
strpos | 查找字符串首次出現(xiàn)的位置 |
stripos | 查找字符串首次出現(xiàn)的位置(不區(qū)分大小寫) |
strrpos | 計(jì)算指定字符串在目標(biāo)字符串中最后一次出現(xiàn)的位置 |
strripos | 計(jì)算指定字符串在目標(biāo)字符串中最后一次出現(xiàn)的位置(不區(qū)分大小寫) |
例1: strpos—查找字符串首次出現(xiàn)的位置
int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
返回 needle 在 haystack 中首次出現(xiàn)的數(shù)字位置扫俺。
$newstring = 'abcdef abcdef';
$pos = strpos($newstring, 'a'); //$pos = 0
$pos = strpos($newstring, 'a', 1); // $pos = 7, 不是 0
當(dāng)返回值為0的時(shí)候的要小心,如果是用作判斷條件應(yīng)該用全等號(hào)"==="或"!=="固翰。
4牵舵、修改字符串
方法 | 說明 |
---|---|
strrev | 反轉(zhuǎn)字符串 |
trim | 去除字符串首尾處的空白字符(或者其他字符) |
ltrim | 刪除字符串開頭的空白字符(或其他字符) |
rtrim (別名: chop) | 刪除字符串末端的空白字符(或者其他字符) |
strip_tags | 從字符串中去除 HTML 和 PHP 標(biāo)記 |
wordwrap | 打斷字符串為指定數(shù)量的字串(換行) |
str_pad | 使用另一個(gè)字符串填充字符串為指定長度 |
str_repeat | 重復(fù)一個(gè)字符串 |
strip_tags | 從字符串中去除 HTML 和 PHP 標(biāo)記 |
htmlspecialchars | 將特殊字符轉(zhuǎn)換為 HTML 實(shí)體 |
str_shuffle | 隨機(jī)打亂一個(gè)字符串 |
例1:strrev—反轉(zhuǎn)字符串
php > echo strrev("Hello world!");
!dlrow olleH
例2:從字符串中去除 HTML 和 PHP 標(biāo)記
string strip_tags ( string $str [, string $allowable_tags ] )
該函數(shù)嘗試返回給定的字符串 str
去除空字符、HTML 和 PHP 標(biāo)記后的結(jié)果倦挂。它使用與函數(shù) fgetss()一樣的機(jī)制去除標(biāo)記。
php > $text = '<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>';
php > echo strip_tags($text, '<p><a>'); // 允許 <p> 和 <a>
<p>Test paragraph.</p> <a href="#fragment">Other text</a>
例3:使文本在指定行長度自動(dòng)換行担巩。
string wordwrap ( string $str [, int $width = 75 [, string $break = "\n" [, bool $cut = FALSE ]]] )
參數(shù)說明:str--輸入字符串方援。 width--列寬度。 break--使用可選的break參數(shù)打斷字符串涛癌。 cut--如果cut設(shè)置為TRUE犯戏,字符串總是在指定的width或者之前位置被打斷。因此拳话,如果有的單詞寬度超過了給定的寬度先匪,它將被分隔開來。當(dāng)它是FALSE弃衍,函數(shù)不會(huì)分割單詞呀非,哪怕width小于單詞寬度。
php > $text = "A very long woooooooooooord.";
php > $newtext = wordwrap($text, 8, "\n", true);
php > echo $newtext;
A very
long
wooooooo
ooooord.
php > $newtext = wordwrap($text, 8, "\n", false);
php > echo $newtext;
A very
long
woooooooooooord.
5、字符串轉(zhuǎn)為數(shù)組
方法 | 說明 |
---|---|
str_split | 將字符串轉(zhuǎn)換為數(shù)組 |
preg_split | 通過一個(gè)正則表達(dá)式分隔字符串岸裙。 |
explode | 使用一個(gè)字符串分割另一個(gè)字符串猖败,返回一個(gè)數(shù)組 |
例1:str_split—將一個(gè)字符串轉(zhuǎn)換為數(shù)組
array str_split ( string $string [, int $split_length = 1 ] )
php > $str = "Hello Friend";
php > $arr = str_split($str, 3);
php > print_r($arr);
Array
(
[0] => Hel
[1] => lo
[2] => Fri
[3] => end
)
例2:preg_split - 通過一個(gè)正則表達(dá)式分隔字符串
array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] )
通過一個(gè)正則表達(dá)式分隔給定字符串.
php > //使用逗號(hào)或空格(包含" ", \r, \t, \n, \f)分隔短語
php > $keywords = preg_split("/[\s,]+/", "hypertext language, programming");
php > print_r($keywords);
Array
(
[0] => hypertext
[1] => language
[2] => programming
)
例3:explode—使用一個(gè)字符串分割另一個(gè)字符串,返回一個(gè)數(shù)組降允。
array explode ( string $delimiter , string $string [, int $limit ] )
此函數(shù)返回由字符串組成的數(shù)組恩闻,每個(gè)元素都是 string 的一個(gè)子串,它們被字符串 delimiter 作為邊界點(diǎn)分割出來剧董。
php > $str = 'one|two|three|four';
php > print_r(explode('|', $str));
Array
(
[0] => one
[1] => two
[2] => three
[3] => four
)
php > print_r(explode('|', $str, 2)); // 正數(shù)的 limit
Array
(
[0] => one
[1] => two|three|four
)
php > print_r(explode('|', $str, -1)); // 負(fù)數(shù)的 limit(自 PHP 5.1 起)
Array
(
[0] => one
[1] => two
[2] => three
)
6幢尚、其它常用函數(shù)
方法 | 說明 |
---|---|
strlen | 返回給定的字符串的長度 |
mb_strlen | 返回具有字符編碼的字符串包含的字符數(shù)(多字節(jié)的字符被計(jì)為 1) |
strval | 獲取變量的字符串值 |
is_string | 檢測變量是否是字符串 |
substr_count | 計(jì)算字串出現(xiàn)的次數(shù) |
str_word_count | 返回字符串中單詞的使用情況 |
例1:獲取字符串長度
$str = '玩去吧a';
echo strlen($str); //輸出10
echo mb_strlen($str); //輸出10
echo mb_strlen($str,'UTF-8'); //輸出4
注:在PHP中,字符串的長度信息是直接存儲(chǔ)在zval結(jié)構(gòu)體中的翅楼,所以函數(shù)strlen()的速度非澄臼#快,時(shí)間復(fù)雜度為O(1)犁嗅。
四边涕、經(jīng)典實(shí)例
1、求出字符串"45,8,7,22,34,1,12"所有數(shù)字的總合褂微。
<?php
$a = '45,8,7,22,34,1,12';
$a_arr = explode(',',$a); //轉(zhuǎn)化為數(shù)組
$sum = array_sum($a_arr); //將數(shù)組中的所有值相加
var_dump($sum);
// 運(yùn)行結(jié)果如下:
nosee123@Chan:~$ php demo9.php
int(129)
擴(kuò)展:如果字符串中的數(shù)字并不是規(guī)范地間隔開來的呢功蜓,這時(shí)要怎么處理。如宠蚂,字符串"aa56 hello,--12--5,10"式撼。
$str = 'aa56 hello,--12--5,10';
preg_match_all('/([0-9]+)/',$str,$reg); //取出字符串中的所有數(shù)字
$sum = array_sum($reg[1]); //將數(shù)組中的所有值相加
var_dump($sum);
// 運(yùn)行結(jié)果如下:
nosee123@Chan:~$ php demo9.php
int(83)
注意:如果要兼容數(shù)字有小數(shù)點(diǎn)的情況,則正則表達(dá)式改為/([0-9]+\.?[0-9]*)/
2求厕、統(tǒng)計(jì)字符串"aaa,abcd,xxxdd;dcba"中每個(gè)字符出現(xiàn)的次數(shù)著隆。
$str ='aaa,abcd,xxxdd;dcba';
$arr = str_split($str); //字符串分割成數(shù)組
$res = array_count_values($arr); //統(tǒng)計(jì)數(shù)組中所有值出現(xiàn)的次數(shù)
var_dump($res);
// 結(jié)果如下:
array (size=7)
'a' => int 5
',' => int 2
'b' => int 2
'c' => int 2
'd' => int 4
'x' => int 3
';' => int 1
其它方法參考:
$res = array();
$arr = str_split($str);
foreach ($arr as $key => $val) {
if (!isset($res[$val])) {
$res[$val] = 1;
} else {
$res[$val] += 1;
}
}
//或者:
$res = array();
$arr = str_split($str);
$unique = array_unique($arr);
foreach ($unique as $key => $val) {
$res[$val] = substr_count($str, $val); // 統(tǒng)計(jì)某字符在字符串中出現(xiàn)的次數(shù)
}
3、不使用PHP函數(shù)呀癣,用方法寫一個(gè)反轉(zhuǎn)字符串的函數(shù)
這里很明顯是不能使用PHP的內(nèi)置函數(shù)strrev()
美浦,下面我們來模擬一個(gè)strrev方法:
$str = 'abcdefg';
function str_rev($str){
$res = '';
$len = strlen($str);
for($i=$len; $i>0;$i--){
$res .= $str[$i-1];
}
return $res;
}
echo str_rev($str); //輸出為:gfedcba
4、將字符串"open_door"轉(zhuǎn)換成"OpenDoor"项栏、"make_by_id"轉(zhuǎn)換成 "MakeById"浦辨。
//方法1:
str_replace(' ','',ucwords(str_replace('_',' ',$str)));
//方法2:
implode('',array_map('ucwords',explode('_',$str)))
五、參考:
1沼沈、官方文檔:
http://php.net/manual/zh/book.strings.php
http://php.net/manual/zh/language.types.string.php
2流酬、相關(guān)書籍:
《PHP經(jīng)典實(shí)例》 David Sklar & Adam Trachtenberg