檢視原始碼 Regex (Elixir v1.16.2)

提供 Elixir 的正規表示式。

Regex 基於 PCRE(Perl 相容正規表示式),並建立在 Erlang 的 :re 模組之上。更多資訊可以在 :re 模組文件 中找到。

Elixir 中的正規表示式可以使用符號 ~r 建立(請參閱 sigil_r/2

# A simple regular expression that matches foo anywhere in the string
~r/foo/

# A regular expression with case insensitive and Unicode options
~r/foo/iu

透過符號建立的正規表示式會預先編譯並儲存在 .beam 檔案中。請注意,如果您正在預編譯 Elixir,這可能會是個問題,請參閱「預編譯」章節以取得更多資訊。

Regex 在內部表示為 Regex 結構。因此,只要需要比對它們,就可以使用 %Regex{}。請記住,所有結構欄位都是私有的。此外,也無法保證來自相同來源的兩個正規表示式相等,例如

~r/(?<foo>.)(?<bar>.)/ == ~r/(?<foo>.)(?<bar>.)/

可能會根據您的機器、位元組序、可用的最佳化和其他因素傳回 truefalse。不過,您可以透過存取 source 欄位來擷取已編譯正規表示式的來源,然後直接比較它們

~r/(?<foo>.)(?<bar>.)/.source == ~r/(?<foo>.)(?<bar>.)/.source

跳脫

跳脫序列分為兩類。

非列印字元

  • \a - 警報,也就是 BEL 字元(十六進位 07)
  • \e - 跳脫(十六進位 1B)
  • \f - 換頁(十六進位 0C)
  • \n - 換行(十六進位 0A)
  • \r - 回車(十六進位 0D)
  • \t - Tab(十六進制 09)
  • \xhh - 十六進制代碼為 hh 的字元
  • \x{hhh..} - 十六進制代碼為 hhh.. 的字元

\u\U 不受支援。其他跳脫序列,例如八進制的 \ddd,受支援但並不建議使用。

一般字元類型

  • \d - 任何十進制數字
  • \D - 任何非十進制數字的字元
  • \h - 任何水平空白字元
  • \H - 任何非水平空白字元的字元
  • \s - 任何空白字元
  • \S - 任何非空白字元的字元
  • \v - 任何垂直空白字元
  • \V - 任何非垂直空白字元的字元
  • \w - 任何「字」元
  • \W - 任何「非字」元

修飾詞

建立 Regex 時可用的修飾詞為

  • :unicode (u) - 啟用 Unicode 特定模式,例如 \p,並導致字元類別,例如 \w\W\s 等,也與 Unicode 相符(請參閱「字元類別」中的以下範例)。它預期在配對時提供有效的 Unicode 字串

  • :caseless (i) - 加入大小寫不敏感

  • :dotall (s) - 導致點與換行符號相符,並將換行符號設定為 anycrlf;新的換行符號設定可以透過設定 (*CR)(*LF)(*CRLF)(*ANY) 根據 :re 文件來覆寫

  • :multiline (m) - 導致 ^$ 標記每一行的開頭和結尾;使用 \A\z 來配對字串的結尾或開頭

  • :extended (x) - 忽略空白字元,除非有跳脫,並允許 # 來界定註解

  • :firstline (f) - 強制未錨定的模式在第一個換行符號之前或在第一個換行符號處進行比對,儘管比對的文字可能會持續超過換行符號

  • :ungreedy (U) - 反轉 regexp 的「貪婪性」(先前的 r 選項已棄用,改用 U

不可用的選項為

  • :anchored - 不可使用,請改用 ^\A
  • :dollar_endonly - 不可使用,請改用 \z
  • :no_auto_capture - 不可使用,請改用 ?:
  • :newline - 不可使用,請在 regexp 開頭使用 (*CR)(*LF)(*CRLF)(*ANYCRLF)(*ANY),依據 :re 文件

擷取

此模組中的許多函式會透過 :capture 選項處理在 regexp 比對中要擷取的內容。支援的值為

  • :all - 所有擷取的子模式,包括完整的比對字串(這是預設值)

  • :first - 僅擷取第一個擷取的子模式,這總是字串中完整的比對部分;所有明確擷取的子模式都會捨棄

  • :all_but_first - 所有比對的子模式,除了第一個,亦即所有明確擷取的子模式,但不包括字串中完整的比對部分

  • :none - 完全不傳回比對的子模式

  • :all_names - 擷取 Regex 中所有命名子模式比對,以子模式名稱的字母順序排列成清單

  • list(binary) - 要擷取的命名擷取清單

字元類別

Regex 支援數個內建的命名字元類別。這些類別是用 [: :] 括住類別名稱在群組內使用。例如

iex> String.match?("123", ~r/^[[:alnum:]]+$/)
true
iex> String.match?("123 456", ~r/^[[:alnum:][:blank:]]+$/)
true

支援的類別名稱為

  • alnum - 字母和數字
  • alpha - 字母
  • blank - 僅空白或標籤
  • cntrl - 控制字元
  • digit - 十進制數字(與 \d 相同)
  • graph - 列印字元,不含空白
  • lower - 小寫字母
  • print - 列印字元,含空白
  • punct - 列印字元,不含字母、數字和空白
  • space - 空白(與 PCRE 8.34 中的 \s 相同)
  • upper - 大寫字母
  • word - 「單字」字元(與 \w 相同)
  • xdigit - 十六進制數字

還有另一個字元類別 ascii,它錯誤地比對拉丁文-1 字元,而不是 POSIX 指定的 0-127 範圍。這無法在不改變其他類別行為的情況下修復,因此我們建議改用 [\\0-\x7f] 比對範圍。

請注意,這些類別的行為可能會根據 Unicode 和其他修飾符而改變

iex> String.match?("josé", ~r/^[[:lower:]]+$/)
false
iex> String.match?("josé", ~r/^[[:lower:]]+$/u)
true
iex> Regex.replace(~r/\s/, "Unicode\u00A0spaces", "-")
"Unicode spaces"
iex> Regex.replace(~r/\s/u, "Unicode\u00A0spaces", "-")
"Unicode-spaces"

預編譯

使用符號建立的正規表示式會預編譯並儲存在 .beam 檔案中。預編譯的正規表示式會在執行階段檢查,並且可能在不同的作業系統和 OTP 版本之間執行得較慢。這很少會造成問題,因為大多數在開發期間共用的 Elixir 程式碼會在目標上編譯(例如相依項、封存檔和 escripts),而且在生產環境中執行時,程式碼必須在目標上編譯(透過 mix compile 或類似指令)或在主機上發布(透過 mix releases 或類似指令),其 OTP、作業系統和架構與目標相符。

如果您知道自己是在與目前系統不同的系統上執行,而且您使用正規表示式執行多重比對,您可以手動呼叫 Regex.recompile/1Regex.recompile!/1 來執行執行階段版本檢查,並在必要時重新編譯正規表示式。

摘要

函式

編譯正規表示式。

編譯正規表示式,並在發生錯誤時引發 Regex.CompileError

跳脫字串,以便在正規表示式中進行逐字比對。

傳回一個布林值,表示是否有配對。

傳回給定的擷取作為一個映射或 nil,如果沒有找到擷取。

傳回正規表示式中的名稱清單。

傳回正規表示式選項,作為字串或清單,視其編譯方式而定。

傳回正規表示式中的底層 re_pattern

必要時重新編譯現有的正規表示式。

重新編譯現有的正規表示式,並在發生錯誤時引發 Regex.CompileError

接收一個正規表示式、一個二進位制和一個替換,傳回一個新的二進位制,其中所有配對都由替換替換。

針對給定的字串執行正規表示式,直到第一次配對。它傳回一個清單,其中包含所有擷取或 nil,如果沒有發生配對。

run/3 相同,但會掃描目標數次,收集正規表示式的所有配對。

傳回正規表示式來源作為二進位制。

根據給定的模式和給定的部分數目,分割給定的目標。

傳回底層 Regex 引擎的版本。

類型

@type t() :: %Regex{
  opts: binary() | [term()],
  re_pattern: term(),
  re_version: term(),
  source: binary()
}

函式

連結到此函式

compile(source, options \\ "")

檢視來源
@spec compile(binary(), binary() | [term()]) :: {:ok, t()} | {:error, any()}

編譯正規表示式。

給定的選項可以是具有代表給定正規表示式選項的字元的二進位制,這些選項提供給 ~r(請參閱 sigil_r/2)符號,或選項清單,正如 Erlang 的 :re 模組所預期的那樣。

如果成功,它會傳回 {:ok, regex},否則傳回 {:error, reason}

範例

iex> Regex.compile("foo")
{:ok, ~r/foo/}

iex> Regex.compile("*foo")
{:error, {'nothing to repeat', 0}}

iex> Regex.compile("foo", "i")
{:ok, ~r/foo/i}

iex> Regex.compile("foo", [:caseless])
{:ok, Regex.compile!("foo", [:caseless])}
連結到此函式

compile!(source, options \\ "")

檢視來源
@spec compile!(binary(), binary() | [term()]) :: t()

編譯正規表示式,並在發生錯誤時引發 Regex.CompileError

@spec escape(String.t()) :: String.t()

跳脫字串,以便在正規表示式中進行逐字比對。

範例

iex> Regex.escape(".")
"\\."

iex> Regex.escape("\\what if")
"\\\\what\\ if"
@spec match?(t(), String.t()) :: boolean()

傳回一個布林值,表示是否有配對。

範例

iex> Regex.match?(~r/foo/, "foo")
true

iex> Regex.match?(~r/foo/, "bar")
false

Elixir 也提供基於文字的配對運算子 =~/2 和函式 String.match?/2,作為針對正規表示式和字串測試字串的替代方案。

連結到此函式

named_captures(regex, string, options \\ [])

檢視來源
@spec named_captures(t(), String.t(), [term()]) :: map() | nil

傳回給定的擷取作為一個映射或 nil,如果沒有找到擷取。

選項

  • :return - 設定為 :index 時,傳回位元組索引和比對長度。預設為 :binary

範例

iex> Regex.named_captures(~r/c(?<foo>d)/, "abcd")
%{"foo" => "d"}

iex> Regex.named_captures(~r/a(?<foo>b)c(?<bar>d)/, "abcd")
%{"bar" => "d", "foo" => "b"}

iex> Regex.named_captures(~r/a(?<foo>b)c(?<bar>d)/, "efgh")
nil
@spec names(t()) :: [String.t()]

傳回正規表示式中的名稱清單。

範例

iex> Regex.names(~r/(?<foo>bar)/)
["foo"]
@spec opts(t()) :: String.t() | [term()]

傳回正規表示式選項,作為字串或清單,視其編譯方式而定。

請參閱 Regex.compile/2 的文件以取得更多資訊。

範例

iex> Regex.opts(~r/foo/m)
"m"

iex> Regex.opts(Regex.compile!("foo", [:caseless]))
[:caseless]
@spec re_pattern(t()) :: term()

傳回正規表示式中的底層 re_pattern

連結到此函式

recompile(regex)

檢視原始碼 (自 1.4.0 起)
@spec recompile(t()) :: {:ok, t()} | {:error, any()}

必要時重新編譯現有的正規表示式。

這會檢查儲存在正規表示式中的版本,並在版本不符時重新編譯正規表示式。

連結到此函式

recompile!(regex)

檢視原始碼 (自 1.4.0 起)
@spec recompile!(t()) :: t()

重新編譯現有的正規表示式,並在發生錯誤時引發 Regex.CompileError

連結到此函式

replace(regex, string, replacement, options \\ [])

檢視來源
@spec replace(t(), String.t(), String.t() | (... -> String.t()), [term()]) ::
  String.t()

接收一個正規表示式、一個二進位制和一個替換,傳回一個新的二進位制,其中所有配對都由替換替換。

替換可以是字串或傳回字串的函式。結果字串用於替換每個比對。

當替換是字串時,它允許使用正規表示式中的括號對比對進行特定擷取,並透過 \N\g{N} 在替換中存取它們,其中 N 是擷取的數字。如果使用 \0,則會插入整個比對。請注意,在正規表示式中,反斜線需要跳脫,因此在實際操作中,您需要使用 \\N\\g{N}

當替換是函式時,它也允許特定擷取。函式可以有 N 個參數,每個參數都對應到一個擷取,第一個參數是整個比對。如果函式預期的參數多於找到的擷取,則其餘參數將接收 ""

選項

  • :global - 當為 false 時,僅替換第一次出現(預設為 true

範例

iex> Regex.replace(~r/d/, "abc", "d")
"abc"

iex> Regex.replace(~r/b/, "abc", "d")
"adc"

iex> Regex.replace(~r/b/, "abc", "[\\0]")
"a[b]c"

iex> Regex.replace(~r/a(b|d)c/, "abcadc", "[\\1]")
"[b][d]"

iex> Regex.replace(~r/\.(\d)$/, "500.5", ".\\g{1}0")
"500.50"

iex> Regex.replace(~r/a(b|d)c/, "abcadc", fn _, x -> "[#{x}]" end)
"[b][d]"

iex> Regex.replace(~r/(\w+)@(\w+).(\w+)/, "abc@def.com", fn _full, _c1, _c2, c3 -> "TLD: #{c3}" end)
"TLD: com"

iex> Regex.replace(~r/a/, "abcadc", "A", global: false)
"Abcadc"
連結到此函式

run(regex, string, options \\ [])

檢視來源
@spec run(t(), binary(), [term()]) :: nil | [binary()] | [{integer(), integer()}]

針對給定的字串執行正規表示式,直到第一次配對。它傳回一個清單,其中包含所有擷取或 nil,如果沒有發生配對。

選項

  • :return - 設定為 :index 時,傳回位元組索引和比對長度。預設為 :binary
  • :capture - 結果中要擷取的內容。請查看 Regex 模組文件,以查看可能的擷取值。
  • :offset - (自 v1.12.0 起) 指定在給定字串中比對的起始偏移量。預設為零。

範例

iex> Regex.run(~r/c(d)/, "abcd")
["cd", "d"]

iex> Regex.run(~r/e/, "abcd")
nil

iex> Regex.run(~r/c(d)/, "abcd", return: :index)
[{2, 2}, {3, 1}]
連結到此函式

scan(regex, string, options \\ [])

檢視來源
@spec scan(t(), String.t(), [term()]) :: [[String.t()]] | [[{integer(), integer()}]]

run/3 相同,但會掃描目標數次,收集正規表示式的所有配對。

傳回的清單包含清單,其中主清單中的每個項目代表一個比對,而次要清單中的每個項目代表擷取的內容。

選項

  • :return - 設定為 :index 時,傳回位元組索引和比對長度。預設為 :binary
  • :capture - 結果中要擷取的內容。請查看 Regex 模組文件,以查看可能的擷取值。
  • :offset - (自 v1.12.0 起) 指定在給定字串中比對的起始偏移量。預設為零。

範例

iex> Regex.scan(~r/c(d|e)/, "abcd abce")
[["cd", "d"], ["ce", "e"]]

iex> Regex.scan(~r/c(?:d|e)/, "abcd abce")
[["cd"], ["ce"]]

iex> Regex.scan(~r/e/, "abcd")
[]

iex> Regex.scan(~r/\p{Sc}/u, "$, £, and €")
[["$"], ["£"], ["€"]]

iex> Regex.scan(~r/=+/, "=ü†ƒ8===", return: :index)
[[{0, 1}], [{9, 3}]]
@spec source(t()) :: String.t()

傳回正規表示式來源作為二進位制。

範例

iex> Regex.source(~r/foo/)
"foo"
連結到此函式

split(regex, string, options \\ [])

檢視來源
@spec split(t(), String.t(), [term()]) :: [String.t()]

根據給定的模式和給定的部分數目,分割給定的目標。

選項

  • :parts - 指定時,將字串分割成給定的部分數。如果未指定,:parts 預設為 :infinity,這會根據給定的模式將字串分割成可能的最大部分數。

  • :trim - 當為 true 時,從結果中移除空字串 ("")。預設為 false

  • :on - 指定要根據哪些擷取來分割字串,以及順序為何。預設為 :first,這表示正規表示式中的擷取不會影響分割程序。請查看 Regex 模組文件,以查看可能的擷取值。

  • :include_captures - 當為 true 時,在結果中包含正規表示式的比對。如果與 :parts 選項結合使用,則比對不會計入最大部分數。預設為 false

範例

iex> Regex.split(~r{-}, "a-b-c")
["a", "b", "c"]

iex> Regex.split(~r{-}, "a-b-c", parts: 2)
["a", "b-c"]

iex> Regex.split(~r{-}, "abc")
["abc"]

iex> Regex.split(~r{}, "abc")
["", "a", "b", "c", ""]

iex> Regex.split(~r{a(?<second>b)c}, "abc")
["", ""]

iex> Regex.split(~r{a(?<second>b)c}, "abc", on: [:second])
["a", "c"]

iex> Regex.split(~r{(x)}, "Elixir", include_captures: true)
["Eli", "x", "ir"]

iex> Regex.split(~r{a(?<second>b)c}, "abc", on: [:second], include_captures: true)
["a", "b", "c"]
連結到此函式

version()

檢視原始碼 (自 1.4.0 起)
@spec version() :: term()

傳回底層 Regex 引擎的版本。