字符串开头和结尾锚点字符串开头和结尾锚点字符串开头和结尾锚点字符串开头和结尾锚点
  • 文章
  • 正则表达式
    • 工具
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容
发表 admin at 2024年3月5日
类别
  • 正则表达式
标签
字符串开头和结尾锚点
  • 简
  • 繁
  • En
关于正则表达式 » 正则表达式教程 » 字符串开头和结尾锚点

Regex 教学
简介
目录
特殊字符
不可打印字符
Regex 引擎内部
字符类别
字符类别减法
字符类别交集
简写字符类别
点
锚点
字词界线
交替
选用项目
重复
群组和截取
反向引用
反向引用,第 2 部分
命名组
相对反向引用
分支重设群组
自由间距和注解
Unicode
模式修改器
原子组
独占量词
前瞻和后顾
环顾,第 2 部分
将文本保留在比对之外
条件
平衡组
递归
子常式
无限递归
递归和量词
递归和截取
递归和反向引用
递归和回溯
POSIX 方括号表达式
零长度比对
持续比对
更多内容
简介
正则表达式快速入门
正则表达式教程
替换字符串教程
应用程序和语言
正则表达式范例
正则表达式参考
替换字符串参考

字符串开头和结尾锚点

到目前为止,我们已经了解了 字面字符、字符类别 和 点。在 regex 中放入其中一个会告诉 regex 引擎尝试比对单一字符。

锚点是不同的种类。它们根本不会比对任何字符。相反地,它们会比对字符之前、之后或之间的位置。它们可用于将 regex 比对「锚定」在特定位置。插入符号 ^ 会比对字符串中第一个字符之前的字符。将 ^a 套用至 abc 会比对 a。 ^b 根本不会比对 abc,因为 b 无法在字符串开头(由 ^ 比对)的正后方比对。请参阅下方 regex 引擎的内部查看。

类似地,$ 会比对字符串中最后一个字符的正后方。 c$ 会在 abc 中比对 c,而 a$ 则完全不会比对。

仅由锚点组成的正则表达式只能找到零长度比对。这可能很有用,但也会产生复杂性,这在教程的最后会说明。

有用的应用

在编程语言中使用正则表达式来验证用户输入时,使用锚点非常重要。如果您在Perl脚本中使用代码if ($input =~ m/\d+/)来查看用户是否输入整数,即使用户输入qsdf4ghjk,它也会接受输入,因为\d+比对4。要使用的正确正则表达式是^\d+$。因为在比对\d+之前必须比对「字符串开头」,并且在比对之后必须比对「字符串结尾」,因此整个字符串必须由数字组成才能比对^\d+$。

用户很容易意外输入空格。当Perl从文本档读取一行时,换行也会保存在变量中。因此在验证输入之前,最好先修剪前导和尾随空白。^\s+比对前导空白,而\s+$比对尾随空白。在Perl中,您可以使用$input =~ s/^\s+|\s+$//g。灵活使用交替和/g让我们能够在单一行代码中运行此操作。

使用^和$作为行开头和行结尾锚点

如果您有一个由多行组成的字符串,例如first line\nsecond line(其中\n表示换行),通常需要处理各行,而不是整个字符串。因此,本教程中讨论的大多数正则表达式引擎都有选项可以扩充两个锚点的意义。^然后可以在字符串开头(在上述字符串中的f之前)以及每个换行符号之后(在\n和s之间)比对。同样地,$仍然比对字符串结尾(在最后一个e之后),以及每个换行符号之前(在e和\n之间)。

在文本编辑器(例如 GNU Emacs)和正则表达式工具中,插入符号和美元符号始终比对每行的开头和结尾。这是合理的,因为这些应用编程为处理整个文件,而不是短字符串。在Ruby和std::regex中,插入符号和美元符号也始终比对每行的开头和结尾。在Boost中,它们缺省比对每行的开头和结尾。使用ECMAScript语法时,Boost允许您使用regex_constants::no_mod_m关闭此功能。

在这个网站上讨论的所有其他编程语言和函数库中,你必须明确激活此延伸功能。它传统上称为「多行模式」。在 Perl 中,你可以通过在正则表达式代码后加上 m 来运行此操作,如下所示:m/^regex$/m;。在 .NET 中,当你指定 RegexOptions.Multiline 时,锚点会在换行符号前后比对,例如 Regex.Match("string", "regex", RegexOptions.Multiline)。

换行字符

关于点的教学页面已经讨论过哪些字符被各种正则表达式风格视为 换行字符。这会在多行模式中对锚点产生同样的影响,以及当美元符号在最后一个换行的结尾之前比对时。锚点处理由单一字符组成的换行符号的方式与每个正则表达式风格中的点相同。

对于锚点来说,当 CR 和 LF 成对出现且正则表达式风格将这两个字符都视为换行符号时,还需要额外考量。 Delphi 和 Java 将 CRLF 视为不可分割的成对字符。 ^ 会在 CRLF 之后比对,而 $ 会在 CRLF 之前比对,但两者都不会在 CRLF 成对字符的中间比对。 JavaScript 和 XPath 将 CRLF 成对字符视为两个换行符号。 ^ 会在 CRLF 的中间和之后比对,而 $ 会在 CRLF 之前和中间比对。

字符串的永久开头和结尾锚点

\A 仅会在字符串的开头比对。同样地,\Z 仅会在字符串的结尾比对。这两个代币绝不会在换行符号中比对。这是本教程中讨论的所有正则表达式风格中的情况,即使你打开「多行模式」也是如此。

JavaScript、POSIX、XML 和 XPath 不支持 \A 和 \Z。你只能使用插入符号和美元符号来运行此目的。

POSIX 正则表达式的 GNU 扩充 使用 \`(反引号)来比对字符串的开头,并使用 \'(单引号)来比对字符串的结尾。

以换行符号结尾的字符串

由于 Perl 在从文件中读取一行时会回传一个结尾有换行符号的字符串,因此 Perl 的正则表达式引擎会比对 $ 在字符串结尾换行符号前的位置,即使已关闭多行模式。Perl 也会比对字符串最结尾的 $,无论该字符是否为换行符号。因此 ^\d+$ 会比对 123,无论主旨字符串是 123 或 123\n。

大多数现代的正则表达式风格都拷贝了此行为。其中包括 .NET、Java、PCRE、Delphi、PHP 和 Python。此行为与「多行模式」等任何设置无关。

在除了 Python 之外的所有这些风格中,\Z 也会比对最后一个换行符号之前的位置。如果您只想要比对字符串最结尾的位置,请使用 \z(小写 z,而非大写 Z)。\A\d+\z 不会比对 123\n。\z 会比对换行符号之后的位置,而 简写字符类别 没有比对换行符号。

在 Python 中,\Z 仅比对字符串最结尾的位置。Python 不支持 \z。

以多个换行符号结尾的字符串

如果一个字符串以多个换行符号结尾,且多行模式已关闭,则 $ 仅会比对在所有可以比对最后一个换行符号之前的位置。对于 \Z 也是如此,与多行模式无关。

Boost 是唯一的例外。在 Boost 中,\Z 可以比对任何数量的尾端换行符号之前的位置,以及字符串最结尾的位置。因此,如果主旨字符串以三个换行符号结尾,Boost 的 \Z 有四个位置可以比对。与其他所有风格一样,Boost 的 \Z 与多行模式无关。Boost 的 $ 仅会在您关闭多行模式时比对字符串最结尾的位置(在 Boost 中缺省为打开)。

深入了解正则表达式引擎

让我们看看当我们尝试将 ^4$ 与 749\n486\n4 (其中 \n 代表换行字符) 相符于多行模式时会发生什么事。一如往常,正则表达式引擎从第一个字符开始:7。正则表达式中的第一个代码为 ^。由于这个代码为零长度代码,引擎不会尝试将它与字符相符,而是与正则表达式引擎迄今为止已达到的字符之前的位置相符。^ 确实与 7 之前的位置相符。引擎接着进展到下一个正则表达式代码:4。由于前一个代码为零长度,正则表达式引擎不会进展到字符串中的下一个字符。它仍然停留在 7。4 是字面字符,与 7 不相符。正则表达式没有其他排列组合,因此引擎从第一个正则表达式代码重新开始,在下一字符:4。这次,^ 无法与 4 之前的位置相符。这个位置之前有一个字符,而且那个字符不是换行。引擎继续进行到 9,并再次失败。下一次尝试,在 \n,也失败了。同样地,\n 之前的位置之前有一个字符,9,而且那个字符不是换行。

接着,正则表达式引擎会到达字符串中的第二个 4。由于 ^ 前面有换行字符,因此它可以在 4 前面的位置进行比对。正则表达式引擎再次前进到下一个正则表达式符号 4,但不会前进字符串中的字符位置。4 会比对 4,而引擎会同时前进正则表达式符号和字符串字符。现在,引擎会尝试在 8 前面的位置(确实:在前面)比对 $。由于这个位置后面有字符,而且该字符不是换行字符,因此美元符号无法在此进行比对。

引擎必须再次尝试比对第一个符号。先前,它已成功在第二个 4 进行比对,因此引擎会继续在下一字符 8 进行比对,而插入符号不会进行比对。在 6 和换行字符中也是一样。

最后,正则表达式引擎会尝试在字符串中的第三个 4 比对第一个符号。成功。之后,引擎会成功地将 4 与 4 进行比对。目前的正则表达式符号会前进到 $,而目前的字符会前进到字符串中的最后一个位置:字符串后的空白。没有任何需要字符才能进行比对的正则表达式符号可以在此进行比对。甚至连 否定字符类别 都无法进行比对。不过,我们尝试比对的是美元符号,而强大的美元符号是个奇怪的野兽。它的长度为零,因此它会尝试比对目前字符前面的位置。这个「字符」是字符串后的空白并无所谓。事实上,美元符号会检查目前的字符。它必须是换行字符或字符串后的空白,才能让 $ 比对目前字符前面的位置。由于范例中是这种情况,因此美元符号成功进行比对。

由于 $ 是正则表达式中的最后一个符号,因此引擎已找到成功的比对:字符串中的最后一个 4。

字串開頭和結尾錨點
  • 简
  • 繁
  • En
關於正規表示式 » 正規表示式教學 » 字串開頭和結尾錨點

Regex 教學
簡介
目錄
特殊字元
不可列印字元
Regex 引擎內部
字元類別
字元類別減法
字元類別交集
簡寫字元類別
點
錨點
字詞界線
交替
選用項目
重複
群組和擷取
反向參照
反向參照,第 2 部分
命名群組
相對反向參照
分支重設群組
自由間距和註解
Unicode
模式修改器
原子群組
獨佔量詞
前瞻和後顧
環顧,第 2 部分
將文字保留在比對之外
條件
平衡群組
遞迴
子常式
無限遞迴
遞迴和量詞
遞迴和擷取
遞迴和反向參照
遞迴和回溯
POSIX 方括號表示式
零長度比對
持續比對
本網站的更多資訊
簡介
正規表示式快速入門
正規表示式教學
替換字串教學
應用程式和語言
正規表示式範例
正規表示式參考
替換字串參考

字串開頭和結尾錨點

到目前為止,我們已經瞭解了 字面字元、字元類別 和 點。在 regex 中放入其中一個會告訴 regex 引擎嘗試比對單一字元。

錨點是不同的種類。它們根本不會比對任何字元。相反地,它們會比對字元之前、之後或之間的位置。它們可用於將 regex 比對「錨定」在特定位置。插入符號 ^ 會比對字串中第一個字元之前的字元。將 ^a 套用至 abc 會比對 a。 ^b 根本不會比對 abc,因為 b 無法在字串開頭(由 ^ 比對)的正後方比對。請參閱下方 regex 引擎的內部檢視。

類似地,$ 會比對字串中最後一個字元的正後方。 c$ 會在 abc 中比對 c,而 a$ 則完全不會比對。

僅由錨點組成的正規表示式只能找到零長度比對。這可能很有用,但也會產生複雜性,這在教學課程的最後會說明。

有用的應用

在程式語言中使用正規表示式來驗證使用者輸入時,使用錨點非常重要。如果您在Perl指令碼中使用程式碼if ($input =~ m/\d+/)來查看使用者是否輸入整數,即使使用者輸入qsdf4ghjk,它也會接受輸入,因為\d+比對4。要使用的正確正規表示式是^\d+$。因為在比對\d+之前必須比對「字串開頭」,並且在比對之後必須比對「字串結尾」,因此整個字串必須由數字組成才能比對^\d+$。

使用者很容易意外輸入空格。當Perl從文字檔讀取一行時,換行也會儲存在變數中。因此在驗證輸入之前,最好先修剪前導和尾隨空白。^\s+比對前導空白,而\s+$比對尾隨空白。在Perl中,您可以使用$input =~ s/^\s+|\s+$//g。靈活使用交替和/g讓我們能夠在單一行程式碼中執行此操作。

使用^和$作為行開頭和行結尾錨點

如果您有一個由多行組成的字串,例如first line\nsecond line(其中\n表示換行),通常需要處理各行,而不是整個字串。因此,本教學課程中討論的大多數正規表示式引擎都有選項可以擴充兩個錨點的意義。^然後可以在字串開頭(在上述字串中的f之前)以及每個換行符號之後(在\n和s之間)比對。同樣地,$仍然比對字串結尾(在最後一個e之後),以及每個換行符號之前(在e和\n之間)。

在文字編輯器(例如 GNU Emacs)和正規表示式工具中,插入符號和美元符號始終比對每行的開頭和結尾。這是合理的,因為這些應用程式設計為處理整個檔案,而不是短字串。在Ruby和std::regex中,插入符號和美元符號也始終比對每行的開頭和結尾。在Boost中,它們預設比對每行的開頭和結尾。使用ECMAScript語法時,Boost允許您使用regex_constants::no_mod_m關閉此功能。

在這個網站上討論的所有其他程式語言和函式庫中,你必須明確啟用此延伸功能。它傳統上稱為「多行模式」。在 Perl 中,你可以透過在正規表示式代碼後加上 m 來執行此操作,如下所示:m/^regex$/m;。在 .NET 中,當你指定 RegexOptions.Multiline 時,錨點會在換行符號前後比對,例如 Regex.Match("string", "regex", RegexOptions.Multiline)。

換行字元

關於點的教學頁面已經討論過哪些字元被各種正規表示式風格視為 換行字元。這會在多行模式中對錨點產生同樣的影響,以及當美元符號在最後一個換行的結尾之前比對時。錨點處理由單一字元組成的換行符號的方式與每個正規表示式風格中的點相同。

對於錨點來說,當 CR 和 LF 成對出現且正規表示式風格將這兩個字元都視為換行符號時,還需要額外考量。 Delphi 和 Java 將 CRLF 視為不可分割的成對字元。 ^ 會在 CRLF 之後比對,而 $ 會在 CRLF 之前比對,但兩者都不會在 CRLF 成對字元的中間比對。 JavaScript 和 XPath 將 CRLF 成對字元視為兩個換行符號。 ^ 會在 CRLF 的中間和之後比對,而 $ 會在 CRLF 之前和中間比對。

字串的永久開頭和結尾錨點

\A 僅會在字串的開頭比對。同樣地,\Z 僅會在字串的結尾比對。這兩個代幣絕不會在換行符號中比對。這是本教學課程中討論的所有正規表示式風格中的情況,即使你開啟「多行模式」也是如此。

JavaScript、POSIX、XML 和 XPath 不支援 \A 和 \Z。你只能使用插入符號和美元符號來執行此目的。

POSIX 正則表示式的 GNU 擴充 使用 \`(反引號)來比對字串的開頭,並使用 \'(單引號)來比對字串的結尾。

以換行符號結尾的字串

由於 Perl 在從檔案中讀取一行時會回傳一個結尾有換行符號的字串,因此 Perl 的正則表示式引擎會比對 $ 在字串結尾換行符號前的位置,即使已關閉多行模式。Perl 也會比對字串最結尾的 $,無論該字元是否為換行符號。因此 ^\d+$ 會比對 123,無論主旨字串是 123 或 123\n。

大多數現代的正則表示式風格都複製了此行為。其中包括 .NET、Java、PCRE、Delphi、PHP 和 Python。此行為與「多行模式」等任何設定無關。

在除了 Python 之外的所有這些風格中,\Z 也會比對最後一個換行符號之前的位置。如果您只想要比對字串最結尾的位置,請使用 \z(小寫 z,而非大寫 Z)。\A\d+\z 不會比對 123\n。\z 會比對換行符號之後的位置,而 簡寫字元類別 沒有比對換行符號。

在 Python 中,\Z 僅比對字串最結尾的位置。Python 不支援 \z。

以多個換行符號結尾的字串

如果一個字串以多個換行符號結尾,且多行模式已關閉,則 $ 僅會比對在所有可以比對最後一個換行符號之前的位置。對於 \Z 也是如此,與多行模式無關。

Boost 是唯一的例外。在 Boost 中,\Z 可以比對任何數量的尾端換行符號之前的位置,以及字串最結尾的位置。因此,如果主旨字串以三個換行符號結尾,Boost 的 \Z 有四個位置可以比對。與其他所有風格一樣,Boost 的 \Z 與多行模式無關。Boost 的 $ 僅會在您關閉多行模式時比對字串最結尾的位置(在 Boost 中預設為開啟)。

深入了解正則表示式引擎

讓我們看看當我們嘗試將 ^4$ 與 749\n486\n4 (其中 \n 代表換行字元) 相符於多行模式時會發生什麼事。一如往常,正規表示式引擎從第一個字元開始:7。正規表示式中的第一個代碼為 ^。由於這個代碼為零長度代碼,引擎不會嘗試將它與字元相符,而是與正規表示式引擎迄今為止已達到的字元之前的位置相符。^ 確實與 7 之前的位置相符。引擎接著進展到下一個正規表示式代碼:4。由於前一個代碼為零長度,正規表示式引擎不會進展到字串中的下一個字元。它仍然停留在 7。4 是字面字元,與 7 不相符。正規表示式沒有其他排列組合,因此引擎從第一個正規表示式代碼重新開始,在下一字元:4。這次,^ 無法與 4 之前的位置相符。這個位置之前有一個字元,而且那個字元不是換行。引擎繼續進行到 9,並再次失敗。下一次嘗試,在 \n,也失敗了。同樣地,\n 之前的位置之前有一個字元,9,而且那個字元不是換行。

接著,正規表示式引擎會到達字串中的第二個 4。由於 ^ 前面有換行字元,因此它可以在 4 前面的位置進行比對。正規表示式引擎再次前進到下一個正規表示式符號 4,但不會前進字串中的字元位置。4 會比對 4,而引擎會同時前進正規表示式符號和字串字元。現在,引擎會嘗試在 8 前面的位置(確實:在前面)比對 $。由於這個位置後面有字元,而且該字元不是換行字元,因此美元符號無法在此進行比對。

引擎必須再次嘗試比對第一個符號。先前,它已成功在第二個 4 進行比對,因此引擎會繼續在下一字元 8 進行比對,而插入符號不會進行比對。在 6 和換行字元中也是一樣。

最後,正規表示式引擎會嘗試在字串中的第三個 4 比對第一個符號。成功。之後,引擎會成功地將 4 與 4 進行比對。目前的正規表示式符號會前進到 $,而目前的字元會前進到字串中的最後一個位置:字串後的空白。沒有任何需要字元才能進行比對的正規表示式符號可以在此進行比對。甚至連 否定字元類別 都無法進行比對。不過,我們嘗試比對的是美元符號,而強大的美元符號是個奇怪的野獸。它的長度為零,因此它會嘗試比對目前字元前面的位置。這個「字元」是字串後的空白並無所謂。事實上,美元符號會檢查目前的字元。它必須是換行字元或字串後的空白,才能讓 $ 比對目前字元前面的位置。由於範例中是這種情況,因此美元符號成功進行比對。

由於 $ 是正規表示式中的最後一個符號,因此引擎已找到成功的比對:字串中的最後一個 4。

Start of String and End of String Anchors
  • 简
  • 繁
  • En
About Regular Expressions » Regular Expressions Tutorial » Start of String and End of String Anchors

Regex Tutorial
Introduction
Table of Contents
Special Characters
Non-Printable Characters
Regex Engine Internals
Character Classes
Character Class Subtraction
Character Class Intersection
Shorthand Character Classes
Dot
Anchors
Word Boundaries
Alternation
Optional Items
Repetition
Grouping & Capturing
Backreferences
Backreferences, part 2
Named Groups
Relative Backreferences
Branch Reset Groups
Free-Spacing & Comments
Unicode
Mode Modifiers
Atomic Grouping
Possessive Quantifiers
Lookahead & Lookbehind
Lookaround, part 2
Keep Text out of The Match
Conditionals
Balancing Groups
Recursion
Subroutines
Infinite Recursion
Recursion & Quantifiers
Recursion & Capturing
Recursion & Backreferences
Recursion & Backtracking
POSIX Bracket Expressions
Zero-Length Matches
Continuing Matches
More on This Site
Introduction
Regular Expressions Quick Start
Regular Expressions Tutorial
Replacement Strings Tutorial
Applications and Languages
Regular Expressions Examples
Regular Expressions Reference
Replacement Strings Reference

Start of String and End of String Anchors

Thus far, we have learned about literal characters, character classes, and the dot. Putting one of these in a regex tells the regex engine to try to match a single character.

Anchors are a different breed. They do not match any character at all. Instead, they match a position before, after, or between characters. They can be used to “anchor” the regex match at a certain position. The caret ^ matches the position before the first character in the string. Applying ^a to abc matches a. ^b does not match abc at all, because the b cannot be matched right after the start of the string, matched by ^. See below for the inside view of the regex engine.

Similarly, $ matches right after the last character in the string. c$ matches c in abc, while a$ does not match at all.

A regex that consists solely of an anchor can only find zero-length matches. This can be useful, but can also create complications that are explained near the end of this tutorial.

Useful Applications

When using regular expressions in a programming language to validate user input, using anchors is very important. If you use the code if ($input =~ m/\d+/) in a Perl script to see if the user entered an integer number, it will accept the input even if the user entered qsdf4ghjk, because \d+ matches the 4. The correct regex to use is ^\d+$. Because “start of string” must be matched before the match of \d+, and “end of string” must be matched right after it, the entire string must consist of digits for ^\d+$ to be able to match.

It is easy for the user to accidentally type in a space. When Perl reads from a line from a text file, the line break is also be stored in the variable. So before validating input, it is good practice to trim leading and trailing whitespace. ^\s+ matches leading whitespace and \s+$ matches trailing whitespace. In Perl, you could use $input =~ s/^\s+|\s+$//g. Handy use of alternation and /g allows us to do this in a single line of code.

Using ^ and $ as Start of Line and End of Line Anchors

If you have a string consisting of multiple lines, like first line\nsecond line (where \n indicates a line break), it is often desirable to work with lines, rather than the entire string. Therefore, most regex engines discussed in this tutorial have the option to expand the meaning of both anchors. ^ can then match at the start of the string (before the f in the above string), as well as after each line break (between \n and s). Likewise, $ still matches at the end of the string (after the last e), and also before every line break (between e and \n).

In text editors like GNU Emacs, and regex tools, the caret and dollar always match at the start and end of each line. This makes sense because those applications are designed to work with entire files, rather than short strings. In Ruby and std::regex the caret and dollar also always match at the start and end of each line. In Boost they match at the start and end of each line by default. Boost allows you to turn this off with regex_constants::no_mod_m when using the ECMAScript grammar.

In all other programming languages and libraries discussed on this website , you have to explicitly activate this extended functionality. It is traditionally called “multi-line mode”. In Perl, you do this by adding an m after the regex code, like this: m/^regex$/m;. In .NET, the anchors match before and after newlines when you specify RegexOptions.Multiline, such as in Regex.Match("string", "regex", RegexOptions.Multiline).

Line Break Characters

The tutorial page about the dot already discussed which characters are seen as line break characters by the various regex flavors. This affects the anchors just as much when in multi-line mode, and when the dollar matches before the end of the final break. The anchors handle line breaks that consist of a single character the same way as the dot in each regex flavor.

For anchors there’s an additional consideration when CR and LF occur as a pair and the regex flavor treats both these characters as line breaks. Delphi and Java treat CRLF as an indivisible pair. ^ matches after CRLF and $ matches before CRLF, but neither match in the middle of a CRLF pair. JavaScript and XPath treat CRLF pairs as two line breaks. ^ matches in the middle of and after CRLF, while $ matches before and in the middle of CRLF.

Permanent Start of String and End of String Anchors

\A only ever matches at the start of the string. Likewise, \Z only ever matches at the end of the string. These two tokens never match at line breaks. This is true in all regex flavors discussed in this tutorial, even when you turn on “multiline mode”.

JavaScript, POSIX, XML, and XPath do not support \A and \Z. You’re stuck with using the caret and dollar for this purpose.

The GNU extensions to POSIX regular expressions use \` (backtick) to match the start of the string, and \' (single quote) to match the end of the string.

Strings Ending with a Line Break

Because Perl returns a string with a newline at the end when reading a line from a file, Perl’s regex engine matches $ at the position before the line break at the end of the string even when multi-line mode is turned off. Perl also matches $ at the very end of the string, regardless of whether that character is a line break. So ^\d+$ matches 123 whether the subject string is 123 or 123\n.

Most modern regex flavors have copied this behavior. That includes .NET, Java, PCRE, Delphi, PHP, and Python. This behavior is independent of any settings such as “multi-line mode”.

In all these flavors except Python, \Z also matches before the final line break. If you only want a match at the absolute very end of the string, use \z (lowercase z instead of uppercase Z). \A\d+\z does not match 123\n. \z matches after the line break, which is not matched by the shorthand character class.

In Python, \Z matches only at the very end of the string. Python does not support \z.

Strings Ending with Multiple Line Breaks

If a string ends with multiple line breaks and multi-line mode is off then $ only matches before the last of those line breaks in all flavors where it can match before the final break. The same is true for \Z regardless of multi-line mode.

Boost is the only exception. In Boost, \Z can match before any number of trailing line breaks as well as at the very end of the string. So if the subject string ends with three line breaks, Boost’s \Z has four positions that it can match at. Like in all other flavors, Boost’s \Z is independent of multi-line mode. Boost’s $ only matches at the very end of the string when you turn off multi-line mode (which is on by default in Boost).

Looking Inside The Regex Engine

Let’s see what happens when we try to match ^4$ to 749\n486\n4 (where \n represents a newline character) in multi-line mode. As usual, the regex engine starts at the first character: 7. The first token in the regular expression is ^. Since this token is a zero-length token, the engine does not try to match it with the character, but rather with the position before the character that the regex engine has reached so far. ^ indeed matches the position before 7. The engine then advances to the next regex token: 4. Since the previous token was zero-length, the regex engine does not advance to the next character in the string. It remains at 7. 4 is a literal character, which does not match 7. There are no other permutations of the regex, so the engine starts again with the first regex token, at the next character: 4. This time, ^ cannot match at the position before the 4. This position is preceded by a character, and that character is not a newline. The engine continues at 9, and fails again. The next attempt, at \n, also fails. Again, the position before \n is preceded by a character, 9, and that character is not a newline.

Then, the regex engine arrives at the second 4 in the string. The ^ can match at the position before the 4, because it is preceded by a newline character. Again, the regex engine advances to the next regex token, 4, but does not advance the character position in the string. 4 matches 4, and the engine advances both the regex token and the string character. Now the engine attempts to match $ at the position before (indeed: before) the 8. The dollar cannot match here, because this position is followed by a character, and that character is not a newline.

Yet again, the engine must try to match the first token again. Previously, it was successfully matched at the second 4, so the engine continues at the next character, 8, where the caret does not match. Same at the 6 and the newline.

Finally, the regex engine tries to match the first token at the third 4 in the string. With success. After that, the engine successfully matches 4 with 4. The current regex token is advanced to $, and the current character is advanced to the very last position in the string: the void after the string. No regex token that needs a character to match can match here. Not even a negated character class. However, we are trying to match a dollar sign, and the mighty dollar is a strange beast. It is zero-length, so it tries to match the position before the current character. It does not matter that this “character” is the void after the string. In fact, the dollar checks the current character. It must be either a newline, or the void after the string, for $ to match the position before the current character. Since that is the case after the example, the dollar matches successfully.

Since $ was the last token in the regex, the engine has found a successful match: the last 4 in the string.

©2015-2025 艾丽卡 support@alaica.com