![](/img/trans.png)
[英]Replace last occurence of regexp in a string which has new lines (replace-regexp-in-string in Emacs)
[英]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
。 在偽代碼中,它大致如下:
給定正則regexp
, replacement
和string
:
將l
設置為字符串的長度並start
0
start
。 創建一個名為matches
的空堆棧以累積新字符串的片段。
只要start
小於l
且regexp
匹配string
中的某個位置,請執行以下操作:
提取與regexp匹配的string
部分,並將其命名為str
。
在更短的字符串str
中用replacement
替換regexp
(這很重要)
將新字符串的以下兩個片段推送到matches
堆棧:
string
的不匹配的初始部分,從匹配的start
到開始
substring str
,其中regexp
的匹配現在已被替換replacement
設置start
到匹配部分的結尾並重復。
最后,以相反的順序連接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.