「實戰elisp」系列旨在講述我使用elisp定製emacs的經驗,拋磚引玉,還請廣大emacs同好不吝賜教——如果真的有廣大emacs使用者的話,哈哈哈。我要編寫乙個elisp函式,其核心邏輯涉及到替換字串中乙個符合某種模式的子串。舉個例子,字串為
"[2020-02-15 sat 14:19]《業務邏輯需要關心同步還是非同步嗎?》"
,需要替換的是其中的[2020-02-15 sat 14:19]
。
這個由日期和時間組成的字首在每一次我按下c-c c t
的時候會自動產生,因為在org-capture-templates
中就是這麼設定的
(setq org-capture-templates
'(("t" "todo" entry (file+headline "~/dropbox/gtd/inbox.org" "tasks")
"* todo %u%?n :properties:n :created_at: %un :id: %(uuidgen-4)n :end:")))
更具體一點,它們產生自其中的轉義序列%u
(詳情可以參見org-mode的文件template expansion)。
經過一番不是特別仔細的搜尋後,我決定用string-match
和replace-match
函式來完成上述替換子串的需求。
然後便鬧了兩個烏龍。
為了匹配形如[2020-02-15 sat 14:19]
這樣的字串,我的直覺便驅使我寫出了這樣的正規表示式
"^[d+-d+-d+ w+ d+:d+]"
在node.js或其它支援shorthand character classes的語言中,上面的正規表示式是可用的。
但是elisp偏偏不是這樣的語言!(elisp所支援的正規表示式語法可以參見這篇文件)因此,在elisp中只好用下面這個正規表示式
"^[[0-9]+-[0-9]+-[0-9]+ [a-za-z]+ [0-9]+:[0-9]+]"
雖然elisp不支援shorthand character classes
,但它確實支援character classes
,但這樣寫出來的正規表示式更長了
"^[[[:digit:]]+-[[:digit:]]+-[[:digit:]]+ [[:alpha:]]+ [[:digit:]]+:[[:digit:]]+]"
我猜你寧可寫前一種對吧。
這貨是用來修改乙個buffer中的內容的……
最後我根據需求的實際情況,綜合使用string-match
、substring
,以及format
實現了替換子串的功能
(defun lt-org--starts-with-timestamp-p (text)
"返回t或nil表示輸入字串是否以乙個inactive timestamp開頭。"
;; emacs的正規表示式並不支援如d和w這樣的類,所以要寫成[0-9]和[a-za-z]的形式
(string-match "^[[0-9]+-[0-9]+-[0-9]+ [a-za-z]+ [0-9]+:[0-9]+]" text))
(defun lt-org--delay-timestamp (text new-timestamp)
"用new-timestamp替換text中的inactive timestamp。
如果text沒有以inactive timestamp開頭,則直接新增new-timestamp。"
(format "%s%s" new-timestamp
(if (lt-org--starts-with-timestamp-p text)
(substring text 22)
text)))
過了很久後,我終於發現了在elisp中做字串替換的正確做法……
只要用replace-regexp-in-string
函式就足夠了
(replace-regexp-in-string "^[[0-9]+-[0-9]+-[0-9]+ [a-za-z]+ [0-9]+:[0-9]+]" "abc" "[2020-02-15 sat 14:19]《業務邏輯需要關心同步還是非同步嗎?》")
結果為"abc《業務邏輯需要關心同步還是非同步嗎?》"
,替換很成功。
閱讀原文
正規表示式語法大全
1 正規表示式 文字框輸入內容控制 2 整數或者小數 0 9 0 9 3 只能輸入數字 0 9 4 只能輸入n位的數字 d 5 只能輸入至少n位的數字 d 6 只能輸入m n位的數字 d 7 只能輸入零和非零開頭的數字 0 1 9 0 9 8 只能輸入有兩位小數的正實數 0 9 0 9 9 只能輸入...
正規表示式語法大全
將下一字元標記為特殊字元 文字 反向引用或八進位制轉義符。例如,n 匹配字元 n n 匹配換行符。序列 匹配 匹配 匹配輸入字串開始的位置。如果設定了 regexp 物件的 multiline 屬性,還會與 n 或 r 之後的位置匹配。匹配輸入字串結尾的位置。如果設定了 regexp 物件的 mul...
JS正規表示式大全
正規表示式中的特殊字元 字元 含意 做為轉意,即通常在 後面的字元不按原來意 釋,如 b 匹配字元 b 當b前面加了反斜桿後 b 轉意為匹配乙個單詞的邊界。或 對正規表示式功能字元的還原,如 匹配它前面元字元0次或多次,a 將匹配a,aa,aaa,加了 後,a 將只匹配 a 匹配乙個輸入或一行的開頭...