檢視原始碼 字串 (Elixir v1.16.2)
Elixir 中的字串是以 UTF-8 編碼的二進位資料。
Elixir 中的字串是一連串的 Unicode 字元,通常寫在雙引號內,例如 "hello"
和 "héllò"
。
如果字串本身必須包含雙引號,則必須使用反斜線來跳脫雙引號,例如:"this is a string with \"double quotes\""
。
你可以使用 <>/2
算子來串接兩個字串
iex> "hello" <> " " <> "world"
"hello world"
此模組中的函式會根據 Unicode 標準,版本 15.1.0 來運作。
內插
Elixir 中的字串也支援內插。這允許你使用 #{}
語法將一些值置於字串中間
iex> name = "joe"
iex> "hello #{name}"
"hello joe"
任何 Elixir 表達式都可以在內插中使用。如果給定字串,則會原樣內插字串。如果給定任何其他值,Elixir 會嘗試使用 String.Chars
協定將其轉換為字串。例如,這允許從內插中輸出整數
iex> "2 + 2 = #{2 + 2}"
"2 + 2 = 4"
如果你要內插的值無法轉換為字串,因為它沒有人類可讀的文字表示形式,則會引發協定錯誤。
跳脫字元
除了允許使用反斜線跳脫雙引號之外,字串也支援下列跳脫字元
\0
- Null 位元組\a
- 鈴聲\b
- 退格\t
- 水平標籤\n
- 換行符號(新行)\v
- 垂直標籤\f
- 表單進紙\r
- 回車\e
- 指令跳脫\s
- 空格\#
- 傳回#
字元本身,略過內插\\
- 單一反斜線\xNN
- 十六進位NN
所表示的位元組\uNNNN
-NNNN
所表示的 Unicode 編碼點\u{NNNNNN}
-NNNNNN
所表示的 Unicode 編碼點
請注意,通常不建議在 Elixir 字串中使用 \xNN
,因為引入無效的位元組序列會使字串無效。如果您必須使用十六進位表示法來引入字元,最好使用 Unicode 編碼點,例如 \uNNNN
。事實上,在進行低階字串操作時,了解 Unicode 編碼點至關重要,因此讓我們接下來詳細探討它們。
Unicode 和編碼點
為了促進多種語言之間的電腦有意義的溝通,需要一個標準,以便一台電腦上的 1 和 0 在傳輸到另一台電腦時具有相同的意義。Unicode 標準作為我們所知幾乎所有字元的官方註冊表:這包括古典和歷史文本、表情符號以及格式化和控制字元。
Unicode 將其庫中的所有字元整理成編碼表,每個字元都有一個唯一的數字索引。此數字索引稱為編碼點。
在 Elixir 中,您可以在字元文字前面使用 ?
來顯示其編碼點
iex> ?a
97
iex> ?ł
322
請注意,大多數 Unicode 編碼表會以其十六進位 (hex) 表示法來表示編碼點,例如 97
轉換為十六進位的 0061
,我們可以使用 \u
跳脫字元後接其編碼點數字來表示 Elixir 字串中的任何 Unicode 字元
iex> "\u0061" === "a"
true
iex> 0x0061 = 97 = ?a
97
十六進位表示法也可以幫助您查詢有關編碼點的資訊,例如 https://codepoints.net/U+0061 有一個關於小寫 a
(又稱編碼點 97)的資料表。請記住,您可以透過呼叫 Integer.to_string/2
來取得數字的十六進位表示法
iex> Integer.to_string(?a, 16)
"61"
UTF-8 編碼與編碼方式
現在我們了解 Unicode 標準是什麼,以及什麼是碼點,我們終於可以討論編碼方式了。碼點是我們儲存的內容,而編碼方式則處理我們如何儲存的:編碼方式是一種實作。換句話說,我們需要一種機制將碼點數字轉換成位元組,以便將它們儲存在記憶體中、寫入磁碟等等。
Elixir 使用 UTF-8 編碼其字串,表示碼點編碼為一系列 8 位元組。UTF-8 是一種可變寬度字元編碼,使用一到四個位元組儲存每個碼點。它能夠編碼所有有效的 Unicode 碼點。我們來看一個範例
iex> string = "héllo"
"héllo"
iex> String.length(string)
5
iex> byte_size(string)
6
儘管上面的字串有 5 個字元,但它使用了 6 個位元組,因為兩個位元組用於表示字元 é
。
字形群集
這個模組也使用字形群集的概念(從現在開始稱為字形)。字形可能包含多個碼點,這些碼點可能被讀者視為單一字元。例如,「é」可以表示為單一的「帶銳音符的 e」碼點,如上面字串 "héllo"
中所示,或表示為字母「e」後接「組合銳音符」(兩個碼點)
iex> string = "\u0065\u0301"
"é"
iex> byte_size(string)
3
iex> String.length(string)
1
iex> String.codepoints(string)
["e", "́"]
iex> String.graphemes(string)
["é"]
儘管它看起來與之前視覺上相同,但上面的範例由兩個字元組成,使用者視為一個字元。
字形也可以是兩個字元,某些語言將其解釋為一個字元。例如,某些語言可能將「ch」視為一個單一字元。但是,由於此資訊取決於區域設定,因此此模組不會考慮它。
一般來說,此模組中的函式依賴於 Unicode 標準,但不包含任何特定區域設定的行為。有關字形的更多資訊,請參閱 Unicode 標準附錄 #29。
有關將二進位制轉換為不同編碼和 Unicode 正規化機制的資訊,請參閱 Erlang 的 :unicode
模組。
字串與二進位制運算
為了根據 Unicode 標準執行,此模組中的許多函式以線性時間執行,因為它們需要考慮適當的 Unicode 碼點來遍歷整個字串。
例如,String.length/1
會隨著輸入的增加而花費更長的時間。另一方面,Kernel.byte_size/1
總是以常數時間執行(即無論輸入大小如何)。
這表示與直接使用二進位制的較低層級運算相比,使用此模組中的函式通常會有效能成本
Kernel.binary_part/3
- 擷取二進制的一部分Kernel.bit_size/1
和Kernel.byte_size/1
- 與大小相關的函式Kernel.is_bitstring/1
和Kernel.is_binary/1
- 類型檢查函式- 另外還有許多函式可於
:binary
模組 中用於處理二進制(位元組)
二進制語法 <<>>
中也提供 utf8
修飾詞。它可用於比對二進制/字串中的編碼點
iex> <<eacute::utf8>> = "é"
iex> eacute
233
您也可以透過呼叫 String.to_charlist/1
,將字串完全轉換成整數編碼點清單,在 Elixir 中稱為「字元清單」
iex> String.to_charlist("héllo")
[104, 233, 108, 108, 111]
如果您想要查看字串的底層位元組,而不是其編碼點,一個常見的技巧是將空位元組 <<0>>
串聯到它
iex> "héllo" <> <<0>>
<<104, 195, 169, 108, 108, 111, 0>>
或者,您可以透過傳遞選項給 IO.inspect/2
來檢視字串的二進制表示
IO.inspect("héllo", binaries: :as_binaries)
#=> <<104, 195, 169, 108, 108, 111>>
自我同步
UTF-8 編碼是自我同步的。這表示如果遇到格式錯誤的資料(即根據編碼定義不可能存在的資料),只需要拒絕一個編碼點。
此模組仰賴此行為來忽略此類無效字元。例如,即使將無效編碼點傳入 length/1
,它仍會傳回正確的結果。
換句話說,此模組預期無效資料會在其他地方被偵測到,通常是在從外部來源擷取資料時。例如,從資料庫讀取字串的驅動程式將負責檢查編碼的有效性。 String.chunk/2
可用於將字串分解成有效和無效的部分。
編譯二進制模式
此模組中的許多函式都使用模式。例如, String.split/3
可以根據模式將字串分割成多個字串。此模式可以是字串、字串清單或編譯模式
iex> String.split("foo bar", " ")
["foo", "bar"]
iex> String.split("foo bar!", [" ", "!"])
["foo", "bar", ""]
iex> pattern = :binary.compile_pattern([" ", "!"])
iex> String.split("foo bar!", pattern)
["foo", "bar", ""]
當相同比對會重複執行多次時,編譯模式會很有用。但請注意,編譯模式無法儲存在模組屬性中,因為模式是在執行時產生,且無法在編譯時保留。
摘要
函數
傳回給定 UTF-8 字串
的 位置
上的字元。如果 位置
大於 字串
長度,則傳回 nil
。
計算兩個字串之間的 bag 距離。
根據 模式
將給定字串中的第一個字元轉換為大寫,其餘字元轉換為小寫。
將字串分割成具有共同特徵的字元區塊。
傳回以字串編碼的碼點清單。
搜尋 字串
是否包含任何給定的 內容
。
根據 模式
將給定字串中的所有字元轉換為小寫。
傳回 主旨
字串重複 n
次的結果。
如果 字串
以任何給定的字尾結尾,則傳回 true
。
如果 字串1
與 字串2
正規相等,則傳回 true
。
傳回 UTF-8 字串中的第一個字元,如果字串為空則傳回 nil
。
根據擴充字元集演算法傳回字串中的 Unicode 字元。
計算兩個字串之間的 Jaro 距離(相似度)。
傳回 UTF-8 字串中的最後一個字元,如果字串為空則傳回 nil
。
傳回 UTF-8 字串中的 Unicode 字元數。
檢查 字串
是否符合給定的正規表示式。
傳回表示編輯指令碼的關鍵字清單。
傳回字串中的下一個碼點。
傳回字串中的下一個字元。
將 字串
中的所有字元轉換為由 形式
識別的 Unicode 正規形式。
傳回一個新的字串,以 填補
中的元素填補開頭。
傳回一個新的字串,以 填補
中的元素填補結尾。
檢查字串是否只包含最多 字元限制
的可列印字元。
傳回一個新的字串,以 取代
取代 主旨
中 模式
的出現。
傳回一個新的字串,以 取代
("�"
為預設值) 取代所有無效位元組。
以 取代
取代 字串
中 相符
的所有開頭出現。
如果 字串
中的前綴與 相符
相符,則以 取代
取代前綴。
如果 字串
中的後綴與 相符
相符,則以 取代
取代後綴。
以 取代
取代 字串
中 相符
的所有結尾出現。
反轉給定字串中的字素。
傳回從範圍開頭給定的偏移量到範圍結尾給定的偏移量之間的子字串。
傳回從偏移量 起始
開始且長度為 長度
的子字串。
在每個 Unicode 空白出現處將字串分割為子字串,並忽略開頭和結尾的空白。空白群組視為單一出現。分割不會發生在不換行空白上。
根據模式將字串分割成數個部分。
在指定偏移量處將字串分割為兩個部分。當給定的偏移量為負數時,位置會從字串結尾開始計算。
傳回一個可列舉物件,依需求將字串分割。
如果 string
以任何給定的前綴開頭,則回傳 true
。
將字串轉換為現有的原子或建立新的原子。
將字串轉換為字元清單。
將字串轉換為現有的原子,如果原子不存在,則會引發錯誤。
回傳一個浮點數,其文字表示為 string
。
回傳一個整數,其文字表示為 string
。
回傳一個整數,其文字表示為 string
,底數為 base
。
回傳一個字串,其中已移除所有前導和尾隨的 Unicode 空白。
回傳一個字串,其中已移除所有前導和尾隨的 to_trim
字元。
回傳一個字串,其中已移除所有前導的 Unicode 空白。
回傳一個字串,其中已移除所有前導的 to_trim
字元。
回傳一個字串,其中已移除所有尾隨的 Unicode 空白。
回傳一個字串,其中已移除所有尾隨的 to_trim
字元。
根據 mode
將給定字串中的所有字元轉換為大寫。
檢查 string
是否只包含有效字元。
類型
@type codepoint() :: t()
以 UTF-8 編碼的單一 Unicode 碼點。可能是一或多個位元組。
@type grapheme() :: t()
讀者可能視為單一字元的多個碼點
@type pattern() :: t() | [nonempty_binary()] | (compiled_search_pattern :: :binary.cp())
用於 replace/4
和 split/3
等函數中的模式。
必須為下列其中一項
- 字串
- 空清單
- 包含非空字串的清單
- 由
:binary.compile_pattern/1
建立的已編譯搜尋模式
@type t() :: binary()
以 UTF-8 編碼的二進位。
對於分析工具而言,String.t()
和 binary()
類型是等效的。不過,對於閱讀文件的人而言,String.t()
表示它是 UTF-8 編碼的二進位資料。
函式
傳回給定 UTF-8 字串
的 位置
上的字元。如果 位置
大於 字串
長度,則傳回 nil
。
範例
iex> String.at("elixir", 0)
"e"
iex> String.at("elixir", 1)
"l"
iex> String.at("elixir", 10)
nil
iex> String.at("elixir", -1)
"r"
iex> String.at("elixir", -10)
nil
計算兩個字串之間的 bag 距離。
傳回介於 0 到 1 之間的浮點值,代表 string1
和 string2
之間的 bag 距離。
bag 距離旨在作為兩個字串之間距離的有效近似值,以快速排除差異極大的字串。
此演算法概述於 Ilaria Bartolini、Paolo Ciaccia 和 Marco Patella 的「使用近似距離進行度量樹字串比對」論文中。
範例
iex> String.bag_distance("abc", "")
0.0
iex> String.bag_distance("abcd", "a")
0.25
iex> String.bag_distance("abcd", "ab")
0.5
iex> String.bag_distance("abcd", "abc")
0.75
iex> String.bag_distance("abcd", "abcd")
1.0
根據 模式
將給定字串中的第一個字元轉換為大寫,其餘字元轉換為小寫。
mode
可以是 :default
、:ascii
、:greek
或 :turkic
。 :default
模式考量 Unicode 標準中概述的所有非條件轉換。 :ascii
僅將 A 到 Z 的字母大寫。 :greek
包含希臘文中找到的內容敏感對應。 :turkic
正確處理帶有無點變體的字母 i
。
另請參閱 upcase/2
和 capitalize/2
以取得其他轉換。如果您想要此函式的變體,不會將字串的其餘部分轉換為小寫,請參閱 Erlang 的 :string.titlecase/1
。
範例
iex> String.capitalize("abcd")
"Abcd"
iex> String.capitalize("ABCD")
"Abcd"
iex> String.capitalize("fin")
"Fin"
iex> String.capitalize("olá")
"Olá"
將字串分割成具有共同特徵的字元區塊。
特徵可以是兩個選項之一
:valid
- 字串會分割成有效和無效字元序列的區塊:printable
- 字串會分割成可列印和不可列印字元序列的區塊
傳回一個二進位清單,每個二進位只包含一種字元。
如果給定的字串為空,則傳回一個空清單。
範例
iex> String.chunk(<<?a, ?b, ?c, 0>>, :valid)
["abc\0"]
iex> String.chunk(<<?a, ?b, ?c, 0, 0xFFFF::utf16>>, :valid)
["abc\0", <<0xFFFF::utf16>>]
iex> String.chunk(<<?a, ?b, ?c, 0, 0x0FFFF::utf8>>, :printable)
["abc", <<0, 0x0FFFF::utf8>>]
傳回以字串編碼的碼點清單。
若要以其自然整數表示法擷取碼點,請參閱 to_charlist/1
。有關碼點和音位的詳細資訊,請參閱 String
模組文件。
範例
iex> String.codepoints("olá")
["o", "l", "á"]
iex> String.codepoints("оптими зации")
["о", "п", "т", "и", "м", "и", " ", "з", "а", "ц", "и", "и"]
iex> String.codepoints("ἅἪῼ")
["ἅ", "Ἢ", "ῼ"]
iex> String.codepoints("\u00e9")
["é"]
iex> String.codepoints("\u0065\u0301")
["e", "́"]
搜尋 字串
是否包含任何給定的 內容
。
contents
可以是字串、字串清單或已編譯的樣式。如果 contents
是清單,此函式會搜尋 contents
中的任何字串是否為 string
的一部分。
在清單中搜尋字串
如果您想要檢查
string
是否列在contents
中,其中contents
是清單,請改用Enum.member?(contents, string)
。
範例
iex> String.contains?("elixir of life", "of")
true
iex> String.contains?("elixir of life", ["life", "death"])
true
iex> String.contains?("elixir of life", ["death", "mercury"])
false
引數也可以是已編譯的模式
iex> pattern = :binary.compile_pattern(["life", "death"])
iex> String.contains?("elixir of life", pattern)
true
空字串永遠會相符
iex> String.contains?("elixir of life", "")
true
iex> String.contains?("elixir of life", ["", "other"])
true
空清單永遠不會相符
iex> String.contains?("elixir of life", [])
false
iex> String.contains?("", [])
false
請注意,此函式可以在音位邊界內或跨音位邊界進行比對。例如,音位「é」是由字元「e」和銳音符號組成。以下會傳回 true
iex> String.contains?(String.normalize("é", :nfd), "e")
true
然而,如果「é」由單一字元「帶銳音符號的 e」表示,則會傳回 false
iex> String.contains?(String.normalize("é", :nfc), "e")
false
根據 模式
將給定字串中的所有字元轉換為小寫。
模式
可能是 :default
、:ascii
、:greek
或 :turkic
。 :default
模式會考量 Unicode 標準中概述的所有非條件轉換。 :ascii
僅將字母 A 到 Z 轉換成小寫。 :greek
包含在希臘文中找到的內容敏感對應。 :turkic
正確處理帶有非點變體的字母 i。
另請參閱 upcase/2
和 capitalize/2
以進行其他轉換。
範例
iex> String.downcase("ABCD")
"abcd"
iex> String.downcase("AB 123 XPTO")
"ab 123 xpto"
iex> String.downcase("OLÁ")
"olá"
:ascii
模式會忽略 Unicode 字元,並在您知道字串僅包含 ASCII 字元時提供效能更高的實作
iex> String.downcase("OLÁ", :ascii)
"olÁ"
:greek
模式會正確處理希臘文中內容敏感的 sigma
iex> String.downcase("ΣΣ")
"σσ"
iex> String.downcase("ΣΣ", :greek)
"σς"
而 :turkic
會正確處理帶有非點變體的字母 i
iex> String.downcase("Iİ")
"ii̇"
iex> String.downcase("Iİ", :turkic)
"ıi"
@spec duplicate(t(), non_neg_integer()) :: t()
傳回 主旨
字串重複 n
次的結果。
由編譯器內嵌。
範例
iex> String.duplicate("abc", 0)
""
iex> String.duplicate("abc", 1)
"abc"
iex> String.duplicate("abc", 2)
"abcabc"
如果 字串
以任何給定的字尾結尾,則傳回 true
。
後綴
可以是單一後綴或後綴清單。
範例
iex> String.ends_with?("language", "age")
true
iex> String.ends_with?("language", ["youth", "age"])
true
iex> String.ends_with?("language", ["youth", "elixir"])
false
空後綴永遠會相符
iex> String.ends_with?("language", "")
true
iex> String.ends_with?("language", ["", "other"])
true
如果 字串1
與 字串2
正規相等,則傳回 true
。
它會在比較字串前對其執行正規形式正規分解 (NFD)。此函式等同於
String.normalize(string1, :nfd) == String.normalize(string2, :nfd)
如果您打算多次比較多個字串,您可以先將它們正規化,然後直接比較它們,以避免多次正規化傳遞。
範例
iex> String.equivalent?("abc", "abc")
true
iex> String.equivalent?("man\u0303ana", "mañana")
true
iex> String.equivalent?("abc", "ABC")
false
iex> String.equivalent?("nø", "nó")
false
傳回 UTF-8 字串中的第一個字元,如果字串為空則傳回 nil
。
範例
iex> String.first("elixir")
"e"
iex> String.first("եոգլի")
"ե"
iex> String.first("")
nil
根據擴充字元集演算法傳回字串中的 Unicode 字元。
演算法概述於 Unicode 標準附錄 #29,Unicode 文字分段 中。
有關碼點和音位的詳細資訊,請參閱 字串
模組文件。
範例
iex> String.graphemes("Ńaïve")
["Ń", "a", "ï", "v", "e"]
iex> String.graphemes("\u00e9")
["é"]
iex> String.graphemes("\u0065\u0301")
["é"]
計算兩個字串之間的 Jaro 距離(相似度)。
傳回介於 0.0
(等於沒有相似性)和 1.0
(完全相符)之間的浮點值,表示 string1
和 string2
之間的 Jaro 距離。
Jaro 距離量度是針對短字串(例如人名)設計,且最適合短字串。Elixir 本身使用此函式提供「您要找的是不是?」功能。例如,當您在模組中呼叫函式時,如果函式名稱有錯字,我們會嘗試根據 jaro_distance/2
分數建議最相似的函式名稱(如果有)。
範例
iex> String.jaro_distance("Dwayne", "Duane")
0.8222222222222223
iex> String.jaro_distance("even", "odd")
0.0
iex> String.jaro_distance("same", "same")
1.0
傳回 UTF-8 字串中的最後一個字元,如果字串為空則傳回 nil
。
它會遍歷整個字串,找出最後一個音位。
範例
iex> String.last("")
nil
iex> String.last("elixir")
"r"
iex> String.last("եոգլի")
"ի"
@spec length(t()) :: non_neg_integer()
傳回 UTF-8 字串中的 Unicode 字元數。
範例
iex> String.length("elixir")
6
iex> String.length("եոգլի")
5
檢查 字串
是否符合給定的正規表示式。
範例
iex> String.match?("foo", ~r/foo/)
true
iex> String.match?("bar", ~r/foo/)
false
Elixir 也提供基於文字的比對運算子 =~/2
和函式 Regex.match?/2
,作為測試字串是否符合正規表示式的替代方案。
傳回表示編輯指令碼的關鍵字清單。
查看 List.myers_difference/2
以取得更多資訊。
範例
iex> string1 = "fox hops over the dog"
iex> string2 = "fox jumps over the lazy cat"
iex> String.myers_difference(string1, string2)
[eq: "fox ", del: "ho", ins: "jum", eq: "ps over the ", del: "dog", ins: "lazy cat"]
傳回字串中的下一個碼點。
結果是一個元組,包含碼點和字串的其餘部分,或在字串已達尾端時為 nil
。
與 String
模組中的其他函式一樣,next_codepoint/1
可處理無效的 UTF-8 二進位檔。如果字串以不符合 UTF-8 編碼的位元組序列開頭,則傳回元組的第一個元素是包含第一個位元組的二進位檔。
範例
iex> String.next_codepoint("olá")
{"o", "lá"}
iex> invalid = "\x80\x80OK" # first two bytes are invalid in UTF-8
iex> {_, rest} = String.next_codepoint(invalid)
{<<128>>, <<128, 79, 75>>}
iex> String.next_codepoint(rest)
{<<128>>, "OK"}
比較二進制模式配對
二進制模式配對提供類似的方式來分解字串
iex> <<codepoint::utf8, rest::binary>> = "Elixir"
"Elixir"
iex> codepoint
69
iex> rest
"lixir"
儘管不完全相等,因為 codepoint
以整數形式出現,而且模式不會配對無效的 UTF-8。
然而,二進制模式配對更簡單且更有效率,因此請選擇更適合您使用案例的選項。
傳回字串中的下一個字元。
結果是一個包含字素和字串剩餘部分的元組,或者在字串已達其結尾時為 nil
。
範例
iex> String.next_grapheme("olá")
{"o", "lá"}
iex> String.next_grapheme("")
nil
將 字串
中的所有字元轉換為由 形式
識別的 Unicode 正規形式。
無效的 Unicode codepoint 會被略過,而字串的剩餘部分會被轉換。如果您希望演算法在無效的 codepoint 上停止並傳回,請改用 :unicode.characters_to_nfd_binary/1
、:unicode.characters_to_nfc_binary/1
、:unicode.characters_to_nfkd_binary/1
和 :unicode.characters_to_nfkc_binary/1
。
正規化形式 :nfkc
和 :nfkd
不應盲目應用於任意文字。因為它們會抹除許多格式化區別,所以它們會阻止與許多舊有字元集進行往返轉換。
形式
支援的形式為
:nfd
- 正規化形式正規分解。字元依據正規等價性分解,而且多個組合字元會以特定順序排列。:nfc
- 正規化形式正規合成。字元會分解,然後依據正規等價性重新合成。:nfkd
- 正規化形式相容性分解。字元依據相容性等價性分解,而且多個組合字元會以特定順序排列。:nfkc
- 正規化形式相容性合成。字元會分解,然後依據相容性等價性重新合成。
範例
iex> String.normalize("yêṩ", :nfd)
"yêṩ"
iex> String.normalize("leña", :nfc)
"leña"
iex> String.normalize("fi", :nfkd)
"fi"
iex> String.normalize("fi", :nfkc)
"fi"
@spec pad_leading(t(), non_neg_integer(), t() | [t()]) :: t()
傳回一個新的字串,以 填補
中的元素填補開頭。
傳遞字串清單作為 padding
會為每個遺失的項目取用清單中的其中一個元素。如果清單比插入項目的數量還短,填補會從清單的開頭重新開始。傳遞字串 padding
等同於傳遞其中的字素清單。如果沒有給定 padding
,它會預設為空白。
當 count
小於或等於 string
的長度時,會傳回給定的 string
。
如果給定的 padding
包含非字串元素,會引發 ArgumentError
。
範例
iex> String.pad_leading("abc", 5)
" abc"
iex> String.pad_leading("abc", 4, "12")
"1abc"
iex> String.pad_leading("abc", 6, "12")
"121abc"
iex> String.pad_leading("abc", 5, ["1", "23"])
"123abc"
@spec pad_trailing(t(), non_neg_integer(), t() | [t()]) :: t()
傳回一個新的字串,以 填補
中的元素填補結尾。
傳遞字串清單作為 padding
會為每個遺失的項目取用清單中的其中一個元素。如果清單比插入項目的數量還短,填補會從清單的開頭重新開始。傳遞字串 padding
等同於傳遞其中的字素清單。如果沒有給定 padding
,它會預設為空白。
當 count
小於或等於 string
的長度時,會傳回給定的 string
。
如果給定的 padding
包含非字串元素,會引發 ArgumentError
。
範例
iex> String.pad_trailing("abc", 5)
"abc "
iex> String.pad_trailing("abc", 4, "12")
"abc1"
iex> String.pad_trailing("abc", 6, "12")
"abc121"
iex> String.pad_trailing("abc", 5, ["1", "23"])
"abc123"
@spec printable?(t(), 0) :: true
@spec printable?(t(), pos_integer() | :infinity) :: boolean()
檢查字串是否只包含最多 字元限制
的可列印字元。
將一個選用的 character_limit
作為第二個參數。如果 character_limit
是 0
,此函式會傳回 true
。
範例
iex> String.printable?("abc")
true
iex> String.printable?("abc" <> <<0>>)
false
iex> String.printable?("abc" <> <<0>>, 2)
true
iex> String.printable?("abc" <> <<0>>, 0)
true
傳回一個新的字串,以 取代
取代 主旨
中 模式
的出現。
subject
永遠是字串。
pattern
可以是字串、字串清單、正規表示式或已編譯的模式。
replacement
可以是字串或接收配對模式的函式,且必須傳回字串或 iodata 作為替換。
預設會替換所有出現,但此行為可透過 :global
選項控制;請參閱下方的「選項」區段。
選項
:global
- (布林值) 如果true
,pattern
的所有出現都會以replacement
替換,否則只會替換第一次出現。預設為true
範例
iex> String.replace("a,b,c", ",", "-")
"a-b-c"
iex> String.replace("a,b,c", ",", "-", global: false)
"a-b,c"
模式也可以是字串清單,而替換也可以是接收配對的函式
iex> String.replace("a,b,c", ["a", "c"], fn <<char>> -> <<char + 1>> end)
"b,b,d"
當模式是正規表示式時,可以在 replacement
字串中提供 \N
或 \g{N}
來存取正規表示式中的特定擷取。
iex> String.replace("a,b,c", ~r/,(.)/, ",\\1\\g{1}")
"a,bb,cc"
請注意,我們必須跳脫反斜線跳脫字元 (亦即,我們使用 \\N
而不是 \N
來跳脫反斜線;\\g{N}
也是一樣)。透過提供 \0
,可以在替換字串中注入整個配對。
也可以提供已編譯的模式
iex> pattern = :binary.compile_pattern(",")
iex> String.replace("a,b,c", pattern, "[]")
"a[]b[]c"
當提供空字串作為 模式
時,函式會將其視為每個字素之間的隱式空字串,且字串將會穿插。如果提供空字串作為 替換
,則會傳回 主旨
iex> String.replace("ELIXIR", "", ".")
".E.L.I.X.I.R."
iex> String.replace("ELIXIR", "", "")
"ELIXIR"
請注意,此函式可以在字素邊界內或跨字素邊界替換。例如,取字素「é」,它由字元「e」和銳音符號組成。以下只會替換字母「e」,將重音符號移到字母「o」
iex> String.replace(String.normalize("é", :nfd), "e", "o")
"ó"
但是,如果「é」由單一字元「帶銳音符號的 e」表示,則它根本不會被替換
iex> String.replace(String.normalize("é", :nfc), "e", "o")
"é"
傳回一個新的字串,以 取代
("�"
為預設值) 取代所有無效位元組。
範例
iex> String.replace_invalid("asd" <> <<0xFF::8>>)
"asd�"
iex> String.replace_invalid("nem rán bề bề")
"nem rán bề bề"
iex> String.replace_invalid("nem rán b" <> <<225, 187>> <> " bề")
"nem rán b� bề"
iex> String.replace_invalid("nem rán b" <> <<225, 187>> <> " bề", "ERROR!")
"nem rán bERROR! bề"
以 取代
取代 字串
中 相符
的所有開頭出現。
如果沒有出現,則傳回未更動的字串。
如果 比對
是 ""
,此函式會引發 ArgumentError
例外:這是因為此函式會替換 string
開頭處 比對
的所有出現,而無法替換 ""
的「多個」出現。
範例
iex> String.replace_leading("hello world", "hello ", "")
"world"
iex> String.replace_leading("hello hello world", "hello ", "")
"world"
iex> String.replace_leading("hello world", "hello ", "ola ")
"ola world"
iex> String.replace_leading("hello hello world", "hello ", "ola ")
"ola ola world"
此函式可以在字素邊界跨越替換。請參閱 replace/3
以取得更多資訊和範例。
如果 字串
中的前綴與 相符
相符,則以 取代
取代前綴。
如果沒有比對,則傳回未更動的字串。如果 比對
是空字串 (""
),則 替換
僅會附加在 string
之前。
範例
iex> String.replace_prefix("world", "hello ", "")
"world"
iex> String.replace_prefix("hello world", "hello ", "")
"world"
iex> String.replace_prefix("hello hello world", "hello ", "")
"hello world"
iex> String.replace_prefix("world", "hello ", "ola ")
"world"
iex> String.replace_prefix("hello world", "hello ", "ola ")
"ola world"
iex> String.replace_prefix("hello hello world", "hello ", "ola ")
"ola hello world"
iex> String.replace_prefix("world", "", "hello ")
"hello world"
此函式可以在字素邊界跨越替換。請參閱 replace/3
以取得更多資訊和範例。
如果 字串
中的後綴與 相符
相符,則以 取代
取代後綴。
如果沒有比對,則傳回未更動的字串。如果 比對
是空字串 (""
),則 替換
僅會附加在 string
之後。
範例
iex> String.replace_suffix("hello", " world", "")
"hello"
iex> String.replace_suffix("hello world", " world", "")
"hello"
iex> String.replace_suffix("hello world world", " world", "")
"hello world"
iex> String.replace_suffix("hello", " world", " mundo")
"hello"
iex> String.replace_suffix("hello world", " world", " mundo")
"hello mundo"
iex> String.replace_suffix("hello world world", " world", " mundo")
"hello world mundo"
iex> String.replace_suffix("hello", "", " world")
"hello world"
此函式可以在字素邊界跨越替換。請參閱 replace/3
以取得更多資訊和範例。
以 取代
取代 字串
中 相符
的所有結尾出現。
如果沒有出現,則傳回未更動的字串。
如果 比對
是 ""
,此函式會引發 ArgumentError
例外:這是因為此函式會替換 string
結尾處 比對
的所有出現,而無法替換 ""
的「多個」出現。
範例
iex> String.replace_trailing("hello world", " world", "")
"hello"
iex> String.replace_trailing("hello world world", " world", "")
"hello"
iex> String.replace_trailing("hello world", " world", " mundo")
"hello mundo"
iex> String.replace_trailing("hello world world", " world", " mundo")
"hello mundo mundo"
此函式可以在字素邊界跨越替換。請參閱 replace/3
以取得更多資訊和範例。
反轉給定字串中的字素。
範例
iex> String.reverse("abcd")
"dcba"
iex> String.reverse("hello world")
"dlrow olleh"
iex> String.reverse("hello ∂og")
"go∂ olleh"
請記住,反轉同一字串兩次並不一定會產生原始字串
iex> "̀e"
"̀e"
iex> String.reverse("̀e")
"è"
iex> String.reverse(String.reverse("̀e"))
"è"
在第一個範例中,重音符號在母音之前,因此被視為兩個字形。但是,當你反轉它一次時,你會得到母音後跟重音符號,這變成一個字形。再次反轉它將保持它為一個單一字形。
傳回從範圍開頭給定的偏移量到範圍結尾給定的偏移量之間的子字串。
如果範圍的開頭不是給定字串的有效偏移量,或者如果範圍是反向順序,則傳回 ""
。
如果範圍的開頭或結尾為負數,則會先遍歷整個字串,以將負數索引轉換為正數索引。
請記住,此函式使用 Unicode 字形,並將切片視為代表字形偏移量。如果你想以原始位元組分割,請改為查看 Kernel.binary_part/3
或 Kernel.binary_slice/2
範例
iex> String.slice("elixir", 1..3)
"lix"
iex> String.slice("elixir", 1..10)
"lixir"
iex> String.slice("elixir", -4..-1)
"ixir"
iex> String.slice("elixir", -4..6)
"ixir"
iex> String.slice("elixir", -100..100)
"elixir"
對於 start > stop
的範圍,你需要明確地將它們標記為遞增
iex> String.slice("elixir", 2..-1//1)
"ixir"
iex> String.slice("elixir", 1..-2//1)
"lixi"
你可以使用 ../0
作為 0..-1//1
的捷徑,它會原樣傳回整個字串
iex> String.slice("elixir", ..)
"elixir"
步長可以是任何正數。例如,要取得字串的每 2 個字元
iex> String.slice("elixir", 0..-1//2)
"eii"
如果第一個位置在字串結尾之後或在範圍的最後一個位置之後,它會傳回一個空字串
iex> String.slice("elixir", 10..3//1)
""
iex> String.slice("a", 1..1500)
""
@spec slice(t(), integer(), non_neg_integer()) :: grapheme()
傳回從偏移量 起始
開始且長度為 長度
的子字串。
如果偏移量大於字串長度,則傳回 ""
。
請記住,此函式使用 Unicode 字形,並將切片視為代表字形偏移量。如果你想以原始位元組分割,請改為查看 Kernel.binary_part/3
或 Kernel.binary_slice/3
。
範例
iex> String.slice("elixir", 1, 3)
"lix"
iex> String.slice("elixir", 1, 10)
"lixir"
iex> String.slice("elixir", 10, 3)
""
如果開始位置為負數,它會根據字串長度正規化並限制為 0
iex> String.slice("elixir", -4, 4)
"ixir"
iex> String.slice("elixir", -10, 3)
"eli"
如果開始位置大於字串長度,則傳回一個空字串
iex> String.slice("elixir", 10, 1500)
""
在每個 Unicode 空白出現處將字串分割為子字串,並忽略開頭和結尾的空白。空白群組視為單一出現。分割不會發生在不換行空白上。
範例
iex> String.split("foo bar")
["foo", "bar"]
iex> String.split("foo" <> <<194, 133>> <> "bar")
["foo", "bar"]
iex> String.split(" foo bar ")
["foo", "bar"]
iex> String.split("no\u00a0break")
["no\u00a0break"]
根據模式將字串分割成數個部分。
傳回這些部分的清單。
pattern
可以是字串、字串清單、正規表示式或已編譯的模式。
預設情況下,字串會被切成盡可能多的部分,但可透過 :parts
選項控制。
只有當 :trim
選項設為 true
時,才會從結果中移除空字串。
當使用的樣式為正規表示式時,字串會使用 Regex.split/3
來切分。
選項
:parts
(正整數或:infinity
) - 字串最多會被切成此選項指定的數量。如果為:infinity
,字串會被切成所有可能的部份。預設為:infinity
。:trim
(布林值) - 如果為true
,會從結果清單中移除空字串。
如果 pattern
為正規表示式,此函式也會接受 Regex.split/3
接受的所有選項。
範例
使用字串樣式切分
iex> String.split("a,b,c", ",")
["a", "b", "c"]
iex> String.split("a,b,c", ",", parts: 2)
["a", "b,c"]
iex> String.split(" a b c ", " ", trim: true)
["a", "b", "c"]
樣式的清單
iex> String.split("1,2 3,4", [" ", ","])
["1", "2", "3", "4"]
正規表示式
iex> String.split("a,b,c", ~r{,})
["a", "b", "c"]
iex> String.split("a,b,c", ~r{,}, parts: 2)
["a", "b,c"]
iex> String.split(" a b c ", ~r{\s}, trim: true)
["a", "b", "c"]
iex> String.split("abc", ~r{b}, include_captures: true)
["a", "b", "c"]
已編譯的樣式
iex> pattern = :binary.compile_pattern([" ", ","])
iex> String.split("1,2 3,4", pattern)
["1", "2", "3", "4"]
在空字串上切分會傳回字位元
iex> String.split("abc", "")
["", "a", "b", "c", ""]
iex> String.split("abc", "", trim: true)
["a", "b", "c"]
iex> String.split("abc", "", parts: 1)
["abc"]
iex> String.split("abc", "", parts: 3)
["", "a", "bc"]
請注意,此函式可以在字位元界線內或跨界切分。例如,字位元「é」是由字元「e」和銳音符號組成。以下會將字串切成兩部分
iex> String.split(String.normalize("é", :nfd), "e")
["", "́"]
但是,如果「é」由單一字元「帶銳音符號的 e」表示,則它只會將字串切成一部分
iex> String.split(String.normalize("é", :nfc), "e")
["é"]
在指定偏移量處將字串分割為兩個部分。當給定的偏移量為負數時,位置會從字串結尾開始計算。
偏移量會限制在字串長度內。傳回包含兩個元素的元組。
注意:請記住此函式會在字位元上切分,因此它必須線性地遍歷字串。如果您想根據位元組數來切分字串或二進位,請改用 Kernel.binary_part/3
。
範例
iex> String.split_at("sweetelixir", 5)
{"sweet", "elixir"}
iex> String.split_at("sweetelixir", -6)
{"sweet", "elixir"}
iex> String.split_at("abc", 0)
{"", "abc"}
iex> String.split_at("abc", 1000)
{"abc", ""}
iex> String.split_at("abc", -1000)
{"", "abc"}
@spec splitter(t(), pattern(), keyword()) :: Enumerable.t()
傳回一個可列舉物件,依需求將字串分割。
這與 split/3
相反,後者會一次切分整個字串。
此函式在設計上不支援正規表示式。在使用正規表示式時,通常讓正規表示式一次遍歷整個字串會比像此函式一樣分批遍歷更有效率。
選項
- :trim - 當
true
時,不會發出空模式
範例
iex> String.splitter("1,2 3,4 5,6 7,8,...,99999", [" ", ","]) |> Enum.take(4)
["1", "2", "3", "4"]
iex> String.splitter("abcd", "") |> Enum.take(10)
["", "a", "b", "c", "d", ""]
iex> String.splitter("abcd", "", trim: true) |> Enum.take(10)
["a", "b", "c", "d"]
也可以提供已編譯的模式
iex> pattern = :binary.compile_pattern([" ", ","])
iex> String.splitter("1,2 3,4 5,6 7,8,...,99999", pattern) |> Enum.take(4)
["1", "2", "3", "4"]
如果 string
以任何給定的前綴開頭,則回傳 true
。
prefix
可以是字串、字串清單或已編譯的模式。
範例
iex> String.starts_with?("elixir", "eli")
true
iex> String.starts_with?("elixir", ["erlang", "elixir"])
true
iex> String.starts_with?("elixir", ["erlang", "ruby"])
false
空字串永遠會相符
iex> String.starts_with?("elixir", "")
true
iex> String.starts_with?("elixir", ["", "other"])
true
空清單永遠不會相符
iex> String.starts_with?("elixir", [])
false
iex> String.starts_with?("", [])
false
將字串轉換為現有的原子或建立新的原子。
警告:此函式會動態建立原子,而原子不會被垃圾回收。因此,string
不應為不受信任的值,例如從 socket 或網路請求中接收的輸入。可以考慮改用 to_existing_atom/1
。
預設情況下,原子的最大數量為 1_048_576
。可以使用 VM 選項 +t
提高或降低此限制。
原子的最大大小為 255 個 Unicode 碼點。
由編譯器內嵌。
範例
iex> String.to_atom("my_atom")
:my_atom
將字串轉換為字元清單。
具體來說,此函式會取得 UTF-8 編碼的二進位資料,並傳回其整數碼點清單。它類似於 codepoints/1
,但後者傳回的是字串形式的碼點清單。
如果您需要處理位元組,請參閱 :binary
模組。
範例
iex> String.to_charlist("foo")
~c"foo"
將字串轉換為現有的原子,如果原子不存在,則會引發錯誤。
原子的最大大小為 255 個 Unicode 碼點。如果原子不存在,會引發 ArgumentError
。
由編譯器內嵌。
原子和模組
由於 Elixir 是一種編譯語言,因此在模組中定義的原子只有在載入該模組後才會存在,這通常發生在執行模組中的函式時。因此,通常建議只呼叫
String.to_existing_atom/1
來轉換在呼叫to_existing_atom/1
的函式所屬模組中定義的原子。若要從字串安全建立模組名稱本身,建議使用
Module.safe_concat/1
。
範例
iex> _ = :my_atom
iex> String.to_existing_atom("my_atom")
:my_atom
回傳一個浮點數,其文字表示為 string
。
字串
必須是包含小數點的浮點數字串表示。若要將不含小數點的字串解析為浮點數,則應使用 Float.parse/1
。否則,將會引發 ArgumentError
。
由編譯器內嵌。
範例
iex> String.to_float("2.2017764e+0")
2.2017764
iex> String.to_float("3.0")
3.0
String.to_float("3")
** (ArgumentError) argument error
回傳一個整數,其文字表示為 string
。
字串
必須是整數的字串表示。否則,將會引發 ArgumentError
。若要解析可能包含格式錯誤整數的字串,請使用 Integer.parse/1
。
由編譯器內嵌。
範例
iex> String.to_integer("123")
123
傳遞不代表整數的字串會導致錯誤
String.to_integer("invalid data")
** (ArgumentError) argument error
回傳一個整數,其文字表示為 string
,底數為 base
。
由編譯器內嵌。
範例
iex> String.to_integer("3FF", 16)
1023
回傳一個字串,其中已移除所有前導和尾隨的 Unicode 空白。
範例
iex> String.trim("\n abc\n ")
"abc"
回傳一個字串,其中已移除所有前導和尾隨的 to_trim
字元。
範例
iex> String.trim("a abc a", "a")
" abc "
回傳一個字串,其中已移除所有前導的 Unicode 空白。
範例
iex> String.trim_leading("\n abc ")
"abc "
回傳一個字串,其中已移除所有前導的 to_trim
字元。
範例
iex> String.trim_leading("__ abc _", "_")
" abc _"
iex> String.trim_leading("1 abc", "11")
"1 abc"
回傳一個字串,其中已移除所有尾隨的 Unicode 空白。
範例
iex> String.trim_trailing(" abc\n ")
" abc"
回傳一個字串,其中已移除所有尾隨的 to_trim
字元。
範例
iex> String.trim_trailing("_ abc __", "_")
"_ abc "
iex> String.trim_trailing("abc 1", "11")
"abc 1"
根據 mode
將給定字串中的所有字元轉換為大寫。
模式
可能為 :default
、:ascii
、:greek
或 :turkic
。 :default
模式會考量 Unicode 標準中概述的所有非條件轉換。 :ascii
僅將 a 到 z 的字母轉換為大寫。 :greek
包含希臘文中發現的內容敏感對應。 :turkic
適當地處理帶有非點變體的字母 i。
範例
iex> String.upcase("abcd")
"ABCD"
iex> String.upcase("ab 123 xpto")
"AB 123 XPTO"
iex> String.upcase("olá")
"OLÁ"
:ascii
模式會忽略 Unicode 字元,並在您知道字串僅包含 ASCII 字元時提供效能更高的實作
iex> String.upcase("olá", :ascii)
"OLá"
而 :turkic
會正確處理帶有非點變體的字母 i
iex> String.upcase("ıi")
"II"
iex> String.upcase("ıi", :turkic)
"Iİ"
另請參閱 downcase/2
和 capitalize/2
以取得其他轉換。
檢查 string
是否只包含有效字元。
演算法
可以是 :default
或 :fast_ascii
。從驗證角度來看,這兩種演算法是等效的(它們永遠會產生相同的輸出),但 :fast_ascii
在特定場景中可以產生顯著的效能提升。
如果符合下列所有條件,您可能想要嘗試 :fast_ascii
演算法,看看它是否能在您的特定場景中產生效能提升
- 您在 64 位元平台上執行 Erlang/OTP 26 或更新版本
- 您預期大部分字串長度會超過 ~64 位元組
- 您預期大部分字串主要包含 ASCII 碼點
請注意,:fast_ascii
演算法不會影響正確性,您可以預期 String.valid?/2
的輸出與演算法無關。唯一預期的差異是效能,與 :default
演算法相比,預期會隨著字串長度大致線性提升。
範例
iex> String.valid?("a")
true
iex> String.valid?("ø")
true
iex> String.valid?(<<0xFFFF::16>>)
false
iex> String.valid?(<<0xEF, 0xB7, 0x90>>)
true
iex> String.valid?("asd" <> <<0xFFFF::16>>)
false
iex> String.valid?("a", :fast_ascii)
true
iex> String.valid?(4)
** (FunctionClauseError) no function clause matching in String.valid?/2