php字串(String)

來源:互聯網
上載者:User
一個字串 string 就是由一系列的字元組成,其中每個字元等同於一個位元組。這意味著 PHP 只能支援 256 的字元集,因此不支援 Unicode 。詳見字串類型詳解。

Note: string 最大可以達到 2GB。

文法

一個字串可以用 4 種方式表達:

單引號

雙引號

heredoc 文法結構

nowdoc 文法結構(自 PHP 5.3.0 起)

單引號

定義一個字串的最簡單的方法是用單引號把它包圍起來(字元 ')。

要表達一個單引號自身,需在它的前面加個反斜線(\)來轉義。要表達一個反斜線自身,則用兩個反斜線(\\)。其它任何方式的反斜線都會被當成反斜線本身:也就是說如果想使用其它逸出序列例如 \r 或者 \n,並不代表任何特殊含義,就單純是這兩個字元本身。

Note: 不像雙引號和 heredoc 文法結構,在單引號字串中的變數和特殊字元的逸出序列將不會被替換。

<?phpecho 'this is a simple string'; // 可以錄入多行echo 'You can also have embedded newlines instrings this way as it isokay to do'; // 輸出: Arnold once said: "I'll be back"echo 'Arnold once said: "I\'ll be back"'; // 輸出: You deleted C:\*.*?echo 'You deleted C:\\*.*?'; // 輸出: You deleted C:\*.*?echo 'You deleted C:\*.*?'; // 輸出: This will not expand: \n a newlineecho 'This will not expand: \n a newline'; // 輸出: Variables do not $expand $eitherecho 'Variables do not $expand $either';?>

雙引號

如果字串是包圍在雙引號(")中, PHP 將對一些特殊的字元進行解析:

序列

含義

\n

換行(ASCII 字元集中的 LF 或 0x0A (10))

\r

斷行符號(ASCII 字元集中的 CR 或 0x0D (13))

\t

水平定位字元(ASCII 字元集中的 HT 或 0x09 (9))

\v

垂直定位字元(ASCII 字元集中的 VT 或 0x0B (11))(自 PHP 5.2.5 起)

\e

Escape(ASCII 字元集中的 ESC 或 0x1B (27))(自 PHP 5.4.0 起)

\f

換頁(ASCII 字元集中的 FF 或 0x0C (12))(自 PHP 5.2.5 起)

\\

反斜線

\$

美元標記

\"

雙引號

\[0-7]{1,3}

符合該Regex序列的是一個以八進位方式來表達的字元

\x[0-9A-Fa-f]{1,2}

符合該Regex序列的是一個以十六進位方式來表達的字元

和單引號字串一樣,轉義任何其它字元都會導致反斜線被顯示出來。PHP 5.1.1 以前,\{$var} 中的反斜線還不會被顯示出來。

用雙引號定義的字串最重要的特徵是變數會被解析,詳見變數解析。

Heredoc 結構

第三種表達字串的方法是用 heredoc 句法結構:<<<。在該運算子之後要提供一個標識符,然後換行。接下來是字串 string 本身,最後要用前面定義的標識符作為結束標誌。

結束時所引用的標識符必須在該行的第一列,而且,標識符的命名也要像其它標籤一樣遵守 PHP 的規則:只能包含字母、數字和底線,並且必須以字母和底線作為開頭。

Warning

要注意的是結束標識符這行除了可能有一個分號(;)外,絕對不能包含其它字元。這意味著標識符不能縮排,分號的前後也不能有任何空白或定位字元。更重要的是結束標識符的前面必須是個被本地作業系統認可的換行,比如在 UNIX 和 Mac OS X 系統中是 \n,而結束定界符(可能其後有個分號)之後也必須緊跟一個換行。

如果不遵守該規則導致結束標識不“乾淨”,PHP 將認為它不是結束標識符而繼續尋找。如果在檔案結束前也沒有找到一個正確的結束標識符,PHP 將會在最後一行產生一個解析錯誤。

Heredocs 結構不能用來初始化類的屬性。自 PHP 5.3 起,此限制僅對 heredoc 包含變數時有效。

Example #1 非法的樣本

<?phpclass foo {   public $bar = <<<EOTbar   EOT;}?>

Heredoc 結構就象是沒有使用雙引號的雙引號字串,這就是說在 heredoc 結構中單引號不用被轉義,但是上文中列出的逸出序列還可以使用。變數將被替換,但在 heredoc 結構中含有複雜的變數時要格外小心。

Example #2 Heredoc 結構的字串樣本

<?php$str = <<<EODExample of stringspanning multiple linesusing heredoc syntax.EOD; /* 含有變數的更複雜樣本 */class foo{   var $foo;   var $bar;    function foo()   {       $this->foo = 'Foo';       $this->bar = array('Bar1', 'Bar2', 'Bar3');   }} $foo = new foo();$name = 'MyName'; echo <<<EOTMy name is "$name". I am printing some $foo->foo.Now, I am printing some {$foo->bar[1]}.This should print a capital 'A': \x41EOT;?>

以上常式會輸出:

My name is "MyName". I am printing some Foo.
Now, I am printing some Bar2.
This should print a capital 'A': A

也可以把 Heredoc 結構用在函數參數中來傳遞資料:

Example #3 Heredoc 結構在參數中的樣本

<?phpvar_dump(array(<<<EODfoobar!EOD));?>

在 PHP 5.3.0 以後,也可以用 Heredoc 結構來初始化靜態變數和類的屬性和常量:

Example #4 使用 Heredoc 結構來初始化靜態值

<?php// 靜態變數function foo(){   static $bar = <<<LABELNothing in here...LABEL;} // 類的常量、屬性class foo{   const BAR = <<<FOOBARConstant exampleFOOBAR;    public $baz = <<<FOOBARProperty exampleFOOBAR;}?>

Nowdoc 結構

就象 heredoc 結構類似於雙引號字串,Nowdoc 結構是類似於單引號字串的。Nowdoc 結構很象 heredoc 結構,但是 nowdoc 中不進行解析操作。這種結構很適合用於嵌入 PHP 代碼或其它大段文本而無需對其中的特殊字元進行轉義。與 SGML 的 <![CDATA[ ]]> 結構是用來聲明大段的不用解析的文本類似,nowdoc 結構也有相同的特徵。

一個 nowdoc 結構也用和 heredocs 結構一樣的標記 <<<, 但是跟在後面的標識符要用單引號括起來,即 <<<'EOT'。Heredoc 結構的所有規則也同樣適用於 nowdoc 結構,尤其是結束標識符的規則。

Example #6 Nowdoc 結構字串樣本

<?php$str = <<<'EOD'Example of stringspanning multiple linesusing nowdoc syntax.EOD; /* 含有變數的更複雜的樣本 */class foo{   public $foo;   public $bar;    function foo()   {       $this->foo = 'Foo';       $this->bar = array('Bar1', 'Bar2', 'Bar3');   }} $foo = new foo();$name = 'MyName'; echo <<<'EOT'My name is "$name". I am printing some $foo->foo.Now, I am printing some {$foo->bar[1]}.This should not print a capital 'A': \x41EOT;?>

以上常式會輸出:

My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': \x41

Note:

不象 heredoc 結構,nowdoc 結構可以用在任意的待用資料環境中,最典型的樣本是用來初始化類的屬性或常量:

Example #7 待用資料的樣本

<?phpclass foo {   public $bar = <<<'EOT'barEOT;}?>

Note:

Nowdoc 結構是在 PHP 5.3.0 中加入的。

變數解析

當字串用雙引號或 heredoc 結構定義時,其中的變數將會被解析。

這裡共有兩種文法規則:一種簡單規則,一種複雜規則。簡單的文法規則是最常用和最方便的,它可以用最少的代碼在一個 string 中嵌入一個變數,一個 array 的值,或一個 object 的屬性。

複雜規則文法的顯著標記是用花括弧包圍的運算式。

簡單文法

當 PHP 解析器遇到一個貨幣符號($)時,它會和其它很多解析器一樣,去組合盡量多的標識以形成一個合法的變數名。可以用花括弧來明確變數名的界線。

<?php$juice = "apple"; echo "He drank some $juice juice.".PHP_EOL;// Invalid. "s" is a valid character for a variable name, but the variable is $juice.echo "He drank some juice made of $juices.";?>

以上常式會輸出:

He drank some apple juice.
He drank some juice made of .

類似的,一個 array 索引或一個 object 屬性也可被解析。數組索引要用方括弧(])來表示索引結束的邊際,對象屬性則是和上述的變數規則相同。

Example #8 簡單文法樣本

<?php$juices = array("apple", "orange", "koolaid1" => "purple"); echo "He drank some $juices[0] juice.".PHP_EOL;echo "He drank some $juices[1] juice.".PHP_EOL;echo "He drank some juice made of $juice[0]s.".PHP_EOL; // Won't workecho "He drank some $juices[koolaid1] juice.".PHP_EOL; class people {   public $john = "John Smith";   public $jane = "Jane Smith";   public $robert = "Robert Paulsen";   public $smith = "Smith";} $people = new people(); echo "$people->john drank some $juices[0] juice.".PHP_EOL;echo "$people->john then said hello to $people->jane.".PHP_EOL;echo "$people->john's wife greeted $people->robert.".PHP_EOL;echo "$people->robert greeted the two $people->smiths."; // Won't work?>

以上常式會輸出:

He drank some apple juice.
He drank some orange juice.
He drank some juice made of s.
He drank some purple juice.
John Smith drank some apple juice.
John Smith then said hello to Jane Smith.
John Smith's wife greeted Robert Paulsen.
Robert Paulsen greeted the two .

如果想要表達更複雜的結構,請用複雜文法。

複雜(花括弧)文法

複雜文法不是因為其文法複雜而得名,而是因為它可以使用複雜的運算式。

任何具有 string 表達的標量變數,數組單元或對象屬性都可使用此文法。只需簡單地像在 string 以外的地方那樣寫出運算式,然後用花括弧 { 和 } 把它括起來即可。由於 { 無法被轉義,只有 $緊挨著 { 時才會被識別。可以用 {\$ 來表達 {$。下面的樣本可以更好的解釋:

<?php// 顯示所有錯誤error_reporting(E_ALL); $great = 'fantastic'; // 無效,輸出: This is { fantastic}echo "This is { $great}"; // 有效,輸出: This is fantasticecho "This is {$great}";echo "This is ${great}"; // 有效echo "This square is {$square->width}00 centimeters broad."; // 有效,只有通過花括弧文法才能正確解析帶引號的鍵名echo "This works: {$arr['key']}"; // 有效echo "This works: {$arr[4][3]}"; // 這是錯誤的運算式,因為就象 $foo[bar] 的格式在字串以外也是錯的一樣。// 換句話說,只有在 PHP 能找到常量 foo 的前提下才會正常工作;這裡會產生一個// E_NOTICE (undefined constant) 層級的錯誤。echo "This is wrong: {$arr[foo][3]}"; // 有效,當在字串中使用多重數組時,一定要用括弧將它括起來echo "This works: {$arr['foo'][3]}"; // 有效echo "This works: " . $arr['foo'][3]; echo "This works too: {$obj->values[3]->name}"; echo "This is the value of the var named $name: {${$name}}"; echo "This is the value of the var named by the return value of getName(): {${getName()}}"; echo "This is the value of the var named by the return value of \$object->getName(): {${$object->getName()}}"; // 無效,輸出: This is the return value of getName(): {getName()}echo "This is the return value of getName(): {getName()}";?>

也可以在字串中用此文法通過變數來調用類的屬性。

<?phpclass foo {   var $bar = 'I am bar.';} $foo = new foo();$bar = 'bar';$baz = array('foo', 'bar', 'baz', 'quux');echo "{$foo->$bar}\n";echo "{$foo->$baz[1]}\n";?>

以上常式會輸出:

I am bar.

I am bar.

Note:

函數、方法、靜態類變數和類常量只有在 PHP 5 以後才可在 {$} 中使用。然而,只有在該字串被定義的命名空間中才可以將其值作為變數名來訪問。只單一使用花括弧 ({}) 無法處理從函數或方法的傳回值或者類常量以及類靜態變數的值。

<?php// 顯示所有錯誤error_reporting(E_ALL); class beers {   const softdrink = 'rootbeer';   public static $ale = 'ipa';} $rootbeer = 'A & W';$ipa = 'Alexander Keith\'s'; // 有效,輸出: I'd like an A & Wecho "I'd like an {${beers::softdrink}}\n"; // 也有效,輸出: I'd like an Alexander Keith'secho "I'd like an {${beers::$ale}}\n";?>

存取和修改字串中的字元

string 中的字元可以通過一個從 0 開始的下標,用類似 array 結構中的方括弧包含對應的數字來訪問和修改,比如 $str[42]。可以把 string 當成字元組成的 array。函數 substr() 和substr_replace() 可用於操作多於一個字元的情況。

Note: string 也可用花括弧訪問,比如 $str{42}。

Warning

用超出字串長度的下標寫入將會拉長該字串並以空格填充。非整數類型下標會被轉換成整數。非法下標類型會產生一個 E_NOTICE 層級錯誤。用負數下標寫入字串時會產生一個 E_NOTICE 層級錯誤,用負數下標讀取字串時返回Null 字元串。寫入時只用到了賦值字串的第一個字元。用Null 字元串賦值則賦給的值是 NULL 字元。

Warning

PHP 的字串在內部是位元組組成的數組。因此用花括弧訪問或修改字串對多位元組字元集很不安全。僅應對單位元組編碼例如 ISO-8859-1 的字串進行此類操作。

Example #9 一些字串樣本

<?php// 取得字串的第一個字元$str = 'This is a test.';$first = $str[0]; // 取得字串的第三個字元$third = $str[2]; // 取得字串的最後一個字元$str = 'This is still a test.';$last = $str[strlen($str)-1]; // 修改字串的最後一個字元$str = 'Look at the sea';$str[strlen($str)-1] = 'e';?>自 PHP 5.4 起字串下標必須為整數或可轉換為整數的字串,否則會發出警告。之前例如 "foo" 的下標會無聲地轉換成 0。Example #10 PHP 5.3 和 PHP 5.4 的區別<?php$str = 'abc'; var_dump($str['1']);var_dump(isset($str['1'])); var_dump($str['1.0']);var_dump(isset($str['1.0'])); var_dump($str['x']);var_dump(isset($str['x'])); var_dump($str['1x']);var_dump(isset($str['1x']));?>

以上常式在PHP 5.3中的輸出:

string(1) "b"
bool(true)
string(1) "b"
bool(true)
string(1) "a"
bool(true)
string(1) "b"
bool(true)

以上常式在PHP 5.4中的輸出:

string(1) "b"
bool(true)

Warning: Illegal string offset '1.0' in /tmp/t.php on line 7
string(1) "b"
bool(false)

Warning: Illegal string offset 'x' in /tmp/t.php on line 9
string(1) "a"
bool(false)
string(1) "b"
bool(false)

Note:

用 [] 或 {} 訪問任何其它類型(不包括數組或具有相應介面的對象實現)的變數只會無聲地返回 NULL。

Note:

PHP 5.5 增加了直接在字串原型中用 [] 或 {} 訪問字元的支援。

有用的函數和運算子

字串可以用 '.'(點)運算子串連起來,注意 '+'(加號)運算子沒有這個功能。更多資訊參考字串運算子。

對於 string 的操作有很多有用的函數。

可以參考字串函數瞭解大部分函數,進階的尋找與替換功能可以參考Regex函數或 Perl 相容Regex函數。

另外還有 URL 字串函數,也有加密/解密字串的函數(mcrypt 和 mhash)。

最後,可以參考字元類型函數。

轉換成字串

一個值可以通過在其前面加上 (string) 或用 strval() 函數來轉變成字串。在一個需要字串的運算式中,會自動轉換為 string。比如在使用函數 echo 或 print 時,或在一個變數和一個 string進行比較時,就會發生這種轉換。類型和類型轉換可以更好的解釋下面的事情,也可參考函數 settype()。

一個布爾值 boolean 的 TRUE 被轉換成 string 的 "1"。Boolean 的 FALSE 被轉換成 ""(Null 字元串)。這種轉換可以在 boolean 和 string 之間相互進行。

一個整數 integer 或浮點數 float 被轉換為數位字面樣式的 string(包括 float 中的指數部分)。使用指數計數法的浮點數(4.1E+6)也可轉換。

Note:

在指令碼的地區(category LC_NUMERIC)中定義了十進位小數點字元。參見 setlocale()。

數組 array 總是轉換成字串 "Array",因此, echo 和 print 無法顯示出該數組的內容。要顯示某個單元,可以用 echo $arr['foo'] 這種結構。要顯示整個數組內容見下文。

在 PHP 4 中對象 object 總是被轉換成字串 "Object",如果為了調試原因需要列印出對象的值,請繼續閱讀下文。為了得到對象的類的名稱,可以用 get_class() 函數。自 PHP 5 起,適當時可以用 __toString 方法。

資源 resource 總會被轉變成 "Resource id #1" 這種結構的字串,其中的 1 是 PHP 在運行時分配給該 resource 的唯一值。不要依賴此結構,可能會有變更。要得到一個 resource 的類型,可以用函數 get_resource_type()。

NULL 總是被轉變成Null 字元串。

如上面所說的,直接把 array,object 或 resource 轉換成 string 不會得到除了其類型之外的任何有用資訊。可以使用函數 print_r() 和 var_dump() 列出這些類型的內容。

大部分的 PHP 值可以轉變成 string 來永久儲存,這被稱作序列化,可以用函數 serialize() 來實現。如果 PHP 引擎設定支援 WDDX,PHP 值也可被序列化為格式良好的 XML 常值。

字串轉換為數值

當一個字串被當作一個數值來取值,其結果和類型如下:

如果該字串沒有包含 '.','e' 或 'E' 並且其數字值在整型的範圍之內(由 PHP_INT_MAX 所定義),該字串將被當成 integer 來取值。其它所有情況下都被作為 float 來取值。

該字串的開始部分決定了它的值。如果該字串以合法的數值開始,則使用該數值。否則其值為 0(零)。合法數值由可選的加號或減號,後面跟著一個或多個數字(可能有小數點),再跟著可選的指數部分。指數部分由 'e' 或 'E' 後面跟著一個或多個數字構成。

<?php$foo = 1 + "10.5";                // $foo is float (11.5)$foo = 1 + "-1.3e3";              // $foo is float (-1299)$foo = 1 + "bob-1.3e3";           // $foo is integer (1)$foo = 1 + "bob3";                // $foo is integer (1)$foo = 1 + "10 Small Pigs";       // $foo is integer (11)$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)$foo = "10.0 pigs " + 1;          // $foo is float (11)$foo = "10.0 pigs " + 1.0;        // $foo is float (11)?>

更多資訊可以參考 Unix 手冊中的 strtod(3)。

本節中的樣本可以通過複製/粘貼到下面的代碼中來顯示:

<?php

echo "\$foo==$foo; type is " . gettype ($foo) . "<br />\n";

?>

不要想像在 C 語言中的那樣,通過將一個字元轉換成整數以得到其代碼。使用函數 ord() 和 chr() 實現 ASCII 碼和字元間的轉換。

字串類型詳解

PHP 中的 string 的實現方式是一個由位元組組成的數組再加上一個整數指明緩衝區長度。並無如何將位元組轉換成字元的資訊,由程式員來決定。字串由什麼值來組成並無限制;特別的,其值為0(“NUL bytes”)的位元組可以處於字串任何位置(不過有幾個函數,在本手冊中被稱為非“二進位安全”的,也許會把 NUL 位元組之後的資料全都忽略)。

字串類型的此特性解釋了為什麼 PHP 中沒有單獨的“byte”類型 - 已經用字串來代替了。返回非文本值的函數 - 例如從網路通訊端讀取的任意資料 - 仍會返回字串。

由於 PHP 並不特別指明字串的編碼,那字串到底是怎樣編碼的呢?例如字串 "á" 到底是等於 "\xE1"(ISO-8859-1),"\xC3\xA1"(UTF-8,C form),"\x61\xCC\x81"(UTF-8,D form)還是任何其它可能的表達呢?答案是字串會被按照該指令檔相同的編碼方式來編碼。因此如果一個指令碼的編碼是 ISO-8859-1,則其中的字串也會被編碼為 ISO-8859-1,以此類推。不過這並不適用於啟用了 Zend Multibyte 時;此時指令碼可以是以任何方式編碼的(明確指定或被自動檢測)然後被轉換為某種內部編碼,然後字串將被用此方式編碼。注意指令碼的編碼有一些約束(如果啟用了 Zend Multibyte 則是其內部編碼)- 這意味著此編碼應該是 ASCII 的相容超集,例如 UTF-8 或 ISO-8859-1。不過要注意,依賴狀態的編碼其中相同的位元組值可以用於首字母和非首字母而轉換狀態,這可能會造成問題。

當然了,要做到有用,操作文本的函數必須假定字串是如何編碼的。不幸的是,PHP 關於此的函數有很多變種:

某些函數假定字串是以單位元組編碼的,但並不需要將位元組解釋為特定的字元。例如 substr(), strpos(), strlen() 和 strcmp()。理解這些函數的另一種方法是它們作用於記憶體緩衝區,即按照位元組和位元組下標操作。

某些函數被傳遞入了字串的編碼方式,也可能會假定預設無此資訊。例如 htmlentities() 和 mbstring 擴充中的大部分函數。

其它函數使用了目前範圍(見 setlocale()),但是逐位元組操作。例如 strcasecmp(), strtoupper() 和 ucfirst()。這意味著這些函數只能用於單位元組編碼,而且編碼要與地區匹配。例如strtoupper("á") 在地區設定正確並且 á 是單位元組編碼時會返回 "Á"。如果是用 UTF-8 編碼則不會返回正確結果,其結果根據目前範圍有可能返回損壞的值。

最後一些函數會假定字串是使用某特定編碼的,通常是 UTF-8。intl 擴充和 PCRE(上例中僅在使用了 u 修飾符時)擴充中的大部分函數都是這樣。儘管這是由於其特殊用途,utf8_decode() 會假定 UTF-8 編碼而 utf8_encode() 會假定 ISO-8859-1 編碼。

最後,要書寫能夠正確使用 Unicode 的程式依賴於很小心地避免那些可能會損壞資料的函數。要使用來自於 intl 和 mbstring 擴充的函數。不過使用能處理 Unicode 編碼的函數只是個開始。不管用何種語言提供的函數,最基本的還是瞭解 Unicode 規格。例如一個程式如果假定只有大寫和小寫,那可是大錯特錯。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.