簡體   English   中英

Emacs,使用replace-regexp-in-string匹配兩個正則表達式

[英]Emacs, using replace-regexp-in-string to match two regexps

我正在嘗試使用replace-regexp-in-string字符串的兩個部分,但我一次只能得到一個部分。 下面是一個示例,我想從開頭刪除#和空格,從字符串末尾刪除換行符。 當我將兩個調用組合成一個表達式時,我做錯了什么?

;; Test string
(setq inputStr "## Header Stuff
")

;; This doesnt trim the newline
(setq header
      (replace-regexp-in-string "^[#\s]*\\|\n$" "" inputStr) )

;; Each match done separately works though
(setq header
      (replace-regexp-in-string "^[#\s]*" "" inputStr) )
(setq header
      (replace-regexp-in-string "\n$" "" header) )

header
"Header Stuff"

更新:問題似乎是第一個表達式,例如,這將替換換行符, "S"替換為"X"(replace-regexp-in-string "S\\\\|\\n$" "X" inputStr)

看起來像replace-regexp-in-string有一些與空字符串匹配的replace-regexp-in-string意外行為。 以下正則表達式可以達到預期效果(注意+量詞代替* ):

(let ((input-string "## Header Stuff
"))
  (replace-regexp-in-string "\\`[#\s]+\\|\n*\\'" "" input-string))

原因在於replace-regexp-in-string的內部實現,您可以使用Mx find-function 在偽代碼中,它大致如下:

給定正則regexpreplacementstring

  1. l設置為字符串的長度並start 0 start 創建一個名為matches的空堆棧以累積新字符串的片段。

  2. 只要start小於lregexp匹配string中的某個位置,請執行以下操作:

    1. 提取與regexp匹配的string部分,並將其命名為str

    2. 在更短的字符串str中用replacement替換regexp (這很重要)

    3. 將新字符串的以下兩個片段推送到matches堆棧:

      • string的不匹配的初始部分,從匹配的start到開始

      • substring str ,其中regexp的匹配現在已被替換replacement

    4. 設置start到匹配部分的結尾並重復。

  3. 最后,以相反的順序連接matches堆棧上的字符串片段並返回結果。

原始正則表達式的問題發生在循環的第(3)步。 即使正則表達式在完整字符串"## Header stuff\\n"的末尾正確匹配換行符,但當它與單字符字符串"\\n"匹配時,第二次匹配 -匹配空字符串 - 優先於第二個,它用空字符串替換空字符串,無法刪除尾隨換行符。

這可以說是replace-regexp-in-string一個錯誤,但它也顯示了regexp語義是多么棘手,特別是涉及空字符串時。 對我而言,解決方案解決方案更易於閱讀和理解:

(let ((input-string "## Header Stuff
"))
  (setq input-string (replace-regexp-in-string "\\`[#\s]*" "" input-string))
  (setq input-string (replace-regexp-in-string "\n*\\'" "" input-string))
  input-string)

如果你有一個非常新的Emacs(pretest 24.4或更高版本),你也可以使用內置subr-x包中的string-trim-right函數:

(let ((input-string "## Header Stuff
"))
  (string-trim-right (replace-regexp-in-string "\\`[#\s]*" "" input-string)))

順便說一句,我很驚訝地發現,在調查這一點, \\s在Emacs串是寫空格字符的只是以不同的方式。 如果你想類似於Perl的正則表達式行為\\s通配符,您可能需要使用"\\\\s-" (匹配空白語法的任何字符),或"[[:space:]]"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM