# Ruby 字符串(String)
Ruby 中的 String 對象存儲并操作一個或多個字節的任意序列,通常表示那些代表人類語言的字符。
最簡單的字符串是括在單引號(單引號字符)內。在引號標記內的文本是字符串的值:
```
'This is a simple Ruby string literal'
```
如果您需要在單引號字符串內使用單引號字符,那么需要在單引號字符串使用反斜杠,這樣 Ruby 解釋器就不會認為這個單引號字符會終止字符串:
```
'Won\'t you read O\'Reilly\'s book?'
```
反斜杠也能轉義另一個反斜杠,這樣第二個反斜杠本身不會解釋為轉義字符。
以下是 Ruby 中字符串相關的特性。
## 表達式置換
表達式置換是一種使用 #{ 和 } 把任意 Ruby 表達式的值嵌入到字符串中的方式:
```
#!/usr/bin/ruby
x, y, z = 12, 36, 72
puts "The value of x is #{ x }."
puts "The sum of x and y is #{ x + y }."
puts "The average was #{ (x + y + z)/3 }."
```
這將產生以下結果:
```
The value of x is 12.
The sum of x and y is 48.
The average was 40.
```
## 一般的分隔字符串
通過一般的分隔字符串,您可以在以百分號字符(%)為前導的一對匹配的任意分隔字符(例如,!、 (、 {、 <,等等)內創建字符串。Q、 q 和 x 有特殊的意義。一般的分隔字符串可以是:
```
%{Ruby is fun.} 相當于 "Ruby is fun."
%Q{ Ruby is fun. } 相當于 " Ruby is fun. "
%q[Ruby is fun.] 相當于以單引號字符串
%x!ls! 相當于反勾號命令輸出 `ls`
```
## 轉義字符
下標列出了可使用反斜杠符號轉義的轉義字符或非打印字符。
**注意:**在一個雙引號括起的字符串內,轉義字符會被解釋;在一個單引號括起的字符串內,轉義字符會被保留。
| 反斜杠符號 | 十六進制字符 | 描述 |
| --- | --- | --- |
| \a | 0x07 | 報警符 |
| \b | 0x08 | 退格鍵 |
| \cx | | Control-x |
| \C-x | | Control-x |
| \e | 0x1b | 轉義符 |
| \f | 0x0c | 換頁符 |
| \M-\C-x | | Meta-Control-x |
| \n | 0x0a | 換行符 |
| \nnn | | 八進制表示法,其中 n 的范圍為 0.7 |
| \r | 0x0d | 回車符 |
| \s | 0x20 | 空格符 |
| \t | 0x09 | 制表符 |
| \v | 0x0b | 垂直制表符 |
| \x | | 字符 x |
| \xnn | | 十六進制表示法,其中 n 的范圍為 0.9、 a.f 或 A.F |
## 字符編碼
Ruby 的默認字符集是 ASCII,字符可用單個字節表示。如果您使用 UTF-8 或其他現代的字符集,字符可能是用一個到四個字節表示。
您可以在程序開頭使用 $KCODE 改變字符集,如下所示:
```
$KCODE = 'u'
```
下面是 $KCODE 可能的值。
| 編碼 | 描述 |
| --- | --- |
| a | ASCII (與 none 相同)。這是默認的。 |
| e | EUC。 |
| n | None (與 ASCII 相同)。 |
| u | UTF-8。 |
## 字符串內建方法
我們需要有一個 String 對象的實例來調用 String 方法。下面是創建 String 對象實例的方式:
```
new [String.new(str="")]
```
這將返回一個包含 _str_ 副本的新的字符串對象。現在,使用 _str_ 對象,我們可以調用任意可用的實例方法。例如:
```
#!/usr/bin/ruby
myStr = String.new("THIS IS TEST")
foo = myStr.downcase
puts "#{foo}"
```
這將產生以下結果:
```
this is test
```
下面是公共的字符串方法(假設 str 是一個 String 對象):
| 方法 | 描述 |
| --- | --- |
| **str % arg** | 使用格式規范格式化字符串。如果 arg 包含一個以上的替代,那么 arg 必須是一個數組。如需了解更多格式規范的信息,請查看"內核模塊"下的 sprintf。 |
| **str * integer** | 返回一個包含 integer 個 str 的新的字符串。換句話說,str 被重復了 integer 次。 |
| **str + other_str** | 連接 other_str 到 str。 |
| **str << obj** | 連接一個對象到字符串。如果對象是范圍為 0.255 之間的固定數字 Fixnum,則它會被轉換為一個字符。把它與 concat 進行比較。 |
| **str <=> other_str** | 把 str 與 other_str 進行比較,返回 -1(小于)、0(等于)或 1(大于)。比較是區分大小寫的。 |
| **str == obj** | 檢查 str 和 obj 的相等性。如果 obj 不是字符串,則返回 false,如果 str <=> obj,則返回 true,返回 0。 |
| **str =~ obj** | 根據正則表達式模式 obj 匹配 str。返回匹配開始的位置,否則返回 false。 |
| **str =~ obj** | 根據正則表達式模式 obj 匹配 str。返回匹配開始的位置,否則返回 false。 |
| **str.capitalize** | 把字符串轉換為大寫字母顯示。 |
| **str.capitalize!** | 與 capitalize 相同,但是 str 會發生變化并返回。 |
| **str.casecmp** | 不區分大小寫的字符串比較。 |
| **str.center** | 居中字符串。 |
| **str.chomp** | 從字符串末尾移除記錄分隔符($/),通常是 \n。如果沒有記錄分隔符,則不進行任何操作。 |
| **str.chomp!** | 與 chomp 相同,但是 str 會發生變化并返回。 |
| **str.chop** | 移除 str 中的最后一個字符。 |
| **str.chop!** | 與 chop 相同,但是 str 會發生變化并返回。 |
| **str.concat(other_str)** | 連接 other_str 到 str。 |
| **str.count(str, ...)** | 給一個或多個字符集計數。如果有多個字符集,則給這些集合的交集計數。 |
| **str.crypt(other_str)** | 對 str 應用單向加密哈希。參數是兩個字符長的字符串,每個字符的范圍為 a.z、 A.Z、 0.9、 . 或 /。 |
| **str.delete(other_str, ...)** | 返回 str 的副本,參數交集中的所有字符會被刪除。 |
| **str.delete!(other_str, ...)** | 與 delete 相同,但是 str 會發生變化并返回。 |
| **str.downcase** | 返回 str 的副本,所有的大寫字母會被替換為小寫字母。 |
| **str.downcase!** | 與 downcase 相同,但是 str 會發生變化并返回。 |
| **str.dump** | 返回 str 的版本,所有的非打印字符被替換為 \nnn 符號,所有的特殊字符被轉義。 |
| **str.each(separator=$/) { |substr| block }** | 使用參數作為記錄分隔符(默認是 $/)分隔 str,傳遞每個子字符串給被提供的塊。 |
| **str.each_byte { |fixnum| block }** | 傳遞 str 的每個字節給 block,以字節的十進制表示法返回每個字節。 |
| **str.each_line(separator=$/) { |substr| block }** | 使用參數作為記錄分隔符(默認是 $/)分隔 str,傳遞每個子字符串給被提供的 block。 |
| **str.empty?** | 如果 str 為空(即長度為 0),則返回 true。 |
| **str.eql?(other)** | 如果兩個字符串有先攻的長度和內容,則這兩個字符串相等。 |
| **str.gsub(pattern, replacement) [or] str.gsub(pattern) { |match| block }** | 返回 str 的副本,pattern 的所有出現都替換為 replacement 或 block 的值。pattern 通常是一個正則表達式 Regexp;如果是一個字符串 String,則沒有正則表達式元字符被解釋(即,/\d/ 將匹配一個數字,但 '\d' 將匹配一個反斜杠后跟一個 'd')。 |
| **str[fixnum] [or] str[fixnum,fixnum] [or] str[range] [or] str[regexp] [or] str[regexp, fixnum] [or] str[other_str]** | 使用下列的參數引用 str:參數為一個 Fixnum,則返回 fixnum 的字符編碼;參數為兩個 Fixnum,則返回一個從偏移(第一個 fixnum)開始截至到長度(第二個 fixnum)為止的子字符串;參數為 range,則返回該范圍內的一個子字符串;參數為 regexp,則返回匹配字符串的部分;參數為帶有 fixnum 的 regexp,則返回 fixnum 位置的匹配數據;參數為 other_str,則返回匹配 other_str 的子字符串。一個負數的 Fixnum 從字符串的末尾 -1 開始。 |
| **str[fixnum] = fixnum [or] str[fixnum] = new_str [or] str[fixnum, fixnum] = new_str [or] str[range] = aString [or] str[regexp] =new_str [or] str[regexp, fixnum] =new_str [or] str[other_str] = new_str ]** | 替換整個字符串或部分字符串。與 slice! 同義。 |
| **str.gsub!(pattern, replacement) [or] str.gsub!(pattern) { |match| block }** | 執行 String#gsub 的替換,返回 str,如果沒有替換被執行則返回 nil。 |
| **str.hash** | 返回一個基于字符串長度和內容的哈希。 |
| **str.hex** | 把 str 的前導字符當作十六進制數字的字符串(一個可選的符號和一個可選的 0x),并返回相對應的數字。如果錯誤則返回零。 |
| **str.include? other_str [or] str.include? fixnum** | 如果 str 包含給定的字符串或字符,則返回 true。 |
| **str.index(substring [, offset]) [or] str.index(fixnum [, offset]) [or] str.index(regexp [, offset])** | 返回給定子字符串、字符(fixnum)或模式(regexp)在 str 中第一次出現的索引。如果未找到則返回 nil。如果提供了第二個參數,則指定在字符串中開始搜索的位置。 |
| **str.insert(index, other_str)** | 在給定索引的字符前插入 other_str,修改 str。負值索引從字符串的末尾開始計數,并在給定字符后插入。其意圖是在給定的索引處開始插入一個字符串。 |
| **str.inspect** | 返回 str 的可打印版本,帶有轉義的特殊字符。 |
| **str.intern [or] str.to_sym** | 返回與 str 相對應的符號,如果之前不存在,則創建符號。 |
| **str.length** | 返回 str 的長度。把它與 size 進行比較。 |
| **str.ljust(integer, padstr=' ')** | 如果 integer 大于 str 的長度,則返回長度為 integer 的新字符串,新字符串以 str 左對齊,并以 padstr 作為填充。否則,返回 str。 |
| **str.lstrip** | 返回 str 的副本,移除了前導的空格。 |
| **str.lstrip!** | 從 str 中移除前導的空格,如果沒有變化則返回 nil。 |
| **str.match(pattern)** | 如果 pattern 不是正則表達是,則把 pattern 轉換為正則表達式 Regexp,然后在 str 上調用它的匹配方法。 |
| **str.oct** | 把 str 的前導字符當作十進制數字的字符串(一個可選的符號),并返回相對應的數字。如果轉換失敗,則返回 0。 |
| **str.replace(other_str)** | 把 str 中的內容替換為 other_str 中的相對應的值。 |
| **str.reverse** | 返回一個新字符串,新字符串是 str 的倒序。 |
| **str.reverse!** | 逆轉 str,str 會發生變化并返回。 |
| **str.rindex(substring [, fixnum]) [or] str.rindex(fixnum [, fixnum]) [or] str.rindex(regexp [, fixnum])** | 返回給定子字符串、字符(fixnum)或模式(regexp)在 str 中最后一次出現的索引。如果未找到則返回 nil。如果提供了第二個參數,則指定在字符串中結束搜索的位置。超出該點的字符將不被考慮。 |
| **str.rjust(integer, padstr=' ')** | 如果 integer 大于 str 的長度,則返回長度為 integer 的新字符串,新字符串以 str 右對齊,并以 padstr 作為填充。否則,返回 str。 |
| **str.rstrip** | 返回 str 的副本,移除了尾隨的空格。 |
| **str.rstrip!** | 從 str 中移除尾隨的空格,如果沒有變化則返回 nil。 |
| **str.scan(pattern) [or] str.scan(pattern) { |match, ...| block }** | 兩種形式匹配 pattern(可以是一個正則表達式 Regexp 或一個字符串 String)遍歷 str。針對每個匹配,會生成一個結果,結果會添加到結果數組中或傳遞給 block。如果 pattern 不包含分組,則每個獨立的結果由匹配的字符串、>< 組成。如果 pattern 包含分組,每個獨立的結果是一個包含每個分組入口的數組。 |
| **str.slice(fixnum) [or] str.slice(fixnum, fixnum) [or] str.slice(range) [or] str.slice(regexp) [or] str.slice(regexp, fixnum) [or] str.slice(other_str) See str[fixnum], etc. str.slice!(fixnum) [or] str.slice!(fixnum, fixnum) [or] str.slice!(range) [or] str.slice!(regexp) [or] str.slice!(other_str)** | 從 str 中刪除指定的部分,并返回刪除的部分。如果值超出范圍,參數帶有 Fixnum 的形式,將生成一個 IndexError。參數為 range 的形式,將生成一個 RangeError,參數為 Regexp 和 String 的形式,將忽略執行動作。 |
| **str.split(pattern=$;, [limit])** | 基于分隔符,把 str 分成子字符串,并返回這些子字符串的數組。 如果 _pattern_ 是一個字符串 String,那么在分割 str 時,它將作為分隔符使用。如果 pattern 是一個單一的空格,那么 str 是基于空格進行分割,會忽略前導空格和連續空格字符。 如果 _pattern_ 是一個正則表達式 Regexp,則 str 在 pattern 匹配的地方被分割。當 pattern 匹配一個玲長度的字符串時,str 被分割成單個字符。 如果省略了 _pattern_ 參數,則使用 $; 的值。如果 $; 為 nil(默認的),str 基于空格進行分割,就像是指定了 ` ` 作為分隔符一樣。 如果省略了 _limit_ 參數,會抑制尾隨的 null 字段。如果 limit 是一個正數,則最多返回該數量的字段(如果 limit 為 1,則返回整個字符串作為數組中的唯一入口)。如果 limit 是一個負數,則返回的字段數量不限制,且不抑制尾隨的 null 字段。 |
| **str.squeeze([other_str]*)** | 使用為 String#count 描述的程序從 other_str 參數建立一系列字符。返回一個新的字符串,其中集合中出現的相同的字符會被替換為單個字符。如果沒有給出參數,則所有相同的字符都被替換為單個字符。 |
| **str.squeeze!([other_str]*)** | 與 squeeze 相同,但是 str 會發生變化并返回,如果沒有變化則返回 nil。 |
| **str.strip** | 返回 str 的副本,移除了前導的空格和尾隨的空格。 |
| **str.strip!** | 從 str 中移除前導的空格和尾隨的空格,如果沒有變化則返回 nil。 |
| **str.sub(pattern, replacement) [or] str.sub(pattern) { |match| block }** | 返回 str 的副本,pattern 的第一次出現會被替換為 replacement 或 block 的值。pattern 通常是一個正則表達式 Regexp;如果是一個字符串 String,則沒有正則表達式元字符被解釋。 |
| **str.sub!(pattern, replacement) [or] str.sub!(pattern) { |match| block }** | 執行 String#sub 替換,并返回 str,如果沒有替換執行,則返回 nil。 |
| **str.succ [or] str.next** | 返回 str 的繼承。 |
| **str.succ! [or] str.next!** | 相當于 String#succ,但是 str 會發生變化并返回。 |
| **str.sum(n=16)** | 返回 str 中字符的 n-bit 校驗和,其中 n 是可選的 Fixnum 參數,默認為 16。結果是簡單地把 str 中每個字符的二進制值的總和,以 2n - 1 為模。這不是一個特別好的校驗和。 |
| **str.swapcase** | 返回 str 的副本,所有的大寫字母轉換為小寫字母,所有的小寫字母轉換為大寫字母。 |
| **str.swapcase!** | 相當于 String#swapcase,但是 str 會發生變化并返回,如果沒有變化則返回 nil。 |
| **str.to_f** | 返回把 str 中的前導字符解釋為浮點數的結果。超出有效數字的末尾的多余字符會被忽略。如果在 str 的開頭沒有有效數字,則返回 0.0。該方法不會生成異常。 |
| **str.to_i(base=10)** | 返回把 str 中的前導字符解釋為整數基數(基數為 2、 8、 10 或 16)的結果。超出有效數字的末尾的多余字符會被忽略。如果在 str 的開頭沒有有效數字,則返回 0。該方法不會生成異常。 |
| **str.to_s [or] str.to_str** | 返回接收的值。 |
| **str.tr(from_str, to_str)** | 返回 str 的副本,把 from_str 中的字符替換為 to_str 中相對應的字符。如果 to_str 比 from_str 短,那么它會以最后一個字符進行填充。兩個字符串都可以使用 c1.c2 符號表示字符的范圍。如果 from_str 以 ^ 開頭,則表示除了所列出的字符以外的所有字符。 |
| **str.tr!(from_str, to_str)** | 相當于 String#tr,但是 str 會發生變化并返回,如果沒有變化則返回 nil。 |
| **str.tr_s(from_str, to_str)** | 把 str 按照 String#tr 描述的規則進行處理,然后移除會影響翻譯的重復字符。 |
| **str.tr_s!(from_str, to_str)** | 相當于 String#tr_s,但是 str 會發生變化并返回,如果沒有變化則返回 nil。 |
| **str.unpack(format)** | 根據 format 字符串解碼 str(可能包含二進制數據),返回被提取的每個值的數組。format 字符由一系列單字符指令組成。每個指令后可以跟著一個數字,表示重復該指令的次數。星號(*)將使用所有剩余的元素。指令 sSiIlL 每個后可能都跟著一個下劃線(_),為指定類型使用底層平臺的本地尺寸大小,否則使用獨立于平臺的一致的尺寸大小。format 字符串中的空格會被忽略。 |
| **str.upcase** | 返回 str 的副本,所有的小寫字母會被替換為大寫字母。操作是環境不敏感的,只有字符 a 到 z 會受影響。 |
| **str.upcase!** | 改變 str 的內容為大寫,如果沒有變化則返回 nil。 |
| **str.upto(other_str) { |s| block }** |遍歷連續值,以 str 開始,以 other_str 結束(包含),輪流傳遞每個值給 block。String#succ 方法用于生成每個值。 |
## 字符串 unpack 指令 下表列出了方法 String#unpack 的解壓指令。
| 指令 | 返回 | 描述 |
| --- | --- | --- |
| A | String | 移除尾隨的 null 和空格。 |
| a | String | 字符串。 |
| B | String | 從每個字符中提取位(首先是最高有效位)。 |
| b | String | 從每個字符中提取位(首先是最低有效位)。 |
| C | Fixnum | 提取一個字符作為無符號整數。 |
| c | Fixnum | 提取一個字符作為整數。 |
| D, d | Float | 把 sizeof(double) 長度的字符當作原生的 double。 |
| E | Float | 把 sizeof(double) 長度的字符當作 littleendian 字節順序的 double。 |
| e | Float | 把 sizeof(float) 長度的字符當作 littleendian 字節順序的 float。 |
| F, f | Float | 把 sizeof(float) 長度的字符當作原生的 float。 |
| G | Float | 把 sizeof(double) 長度的字符當作 network 字節順序的 double。 |
| g | Float | 把 sizeof(float) 長度的字符當作 network 字節順序的 float。 |
| H | String | 從每個字符中提取十六進制(首先是最高有效位)。 |
| h | String | 從每個字符中提取十六進制(首先是最低有效位)。 |
| I | Integer | 把 sizeof(int) 長度(通過 _ 修改)的連續字符當作原生的 integer。 |
| i | Integer | 把 sizeof(int) 長度(通過 _ 修改)的連續字符當作有符號的原生的 integer。 |
| L | Integer | 把四個(通過 _ 修改)連續字符當作無符號的原生的 long integer。 |
| l | Integer | 把四個(通過 _ 修改)連續字符當作有符號的原生的 long integer。 |
| M | String | 引用可打印的。 |
| m | String | Base64 編碼。 |
| N | Integer | 把四個字符當作 network 字節順序的無符號的 long。 |
| n | Fixnum | 把兩個字符當作 network 字節順序的無符號的 short。 |
| P | String | 把 sizeof(char *) 長度的字符當作指針,并從引用的位置返回 \emph{len} 字符。 |
| p | String | 把 sizeof(char *) 長度的字符當作一個空結束字符的指針。 |
| Q | Integer | 把八個字符當作無符號的 quad word(64 位)。 |
| q | Integer | 把八個字符當作有符號的 quad word(64 位)。 |
| S | Fixnum | 把兩個(如果使用 _ 則不同)連續字符當作 native 字節順序的無符號的 short。 |
| s | Fixnum | 把兩個(如果使用 _ 則不同)連續字符當作 native 字節順序的有符號的 short。 |
| U | Integer | UTF-8 字符,作為無符號整數。 |
| u | String | UU 編碼。 |
| V | Fixnum | 把四個字符當作 little-endian 字節順序的無符號的 long。 |
| v | Fixnum | 把兩個字符當作 little-endian 字節順序的無符號的 short。 |
| w | Integer | BER 壓縮的整數。 |
| X | | 向后跳過一個字符。 |
| x | | 向前跳過一個字符。 |
| Z | String | 和 * 一起使用,移除尾隨的 null 直到第一個 null。 |
| @ | | 跳過 length 參數給定的偏移量。 |
## 實例
嘗試下面的實例,解壓各種數據。
```
"abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
"abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
"abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
"aa".unpack('b8B8') #=> ["10000110", "01100001"]
"aaa".unpack('h2H2c') #=> ["16", "61", 97]
"\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
"now=20is".unpack('M*') #=> ["now is"]
"whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]
```
- Ruby 基礎
- Ruby 簡介
- Ruby 環境
- Ruby 安裝 - Unix
- Ruby 安裝 - Windows
- Ruby 命令行選項
- Ruby 環境變量
- Ruby 語法
- Ruby 數據類型
- Ruby 類和對象
- Ruby 類案例
- Ruby 變量
- Ruby 運算符
- Ruby 注釋
- Ruby 判斷
- Ruby 循環
- Ruby 方法
- Ruby 塊
- Ruby 模塊(Module)
- Ruby 字符串(String)
- Ruby 數組(Array)
- Ruby 哈希(Hash)
- Ruby 日期 & 時間(Date & Time)
- Ruby 范圍(Range)
- Ruby 迭代器
- Ruby 文件的輸入與輸出
- Ruby File 類和方法
- Ruby Dir 類和方法
- Ruby 異常
- Ruby 高級
- Ruby 面向對象
- Ruby 正則表達式
- Ruby 數據庫訪問 - DBI 教程
- Ruby CGI 編程
- Ruby CGI方法
- Ruby CGI Cookies
- Ruby CGI Sessions
- Ruby 發送郵件 - SMATP
- Ruby Socket 編程
- Ruby XML, XSLT 和 XPath 教程
- Ruby Web Services 應用 - SOAP4R
- Ruby 多線程
- 免責聲明