2011-11-25 99 views
1

很多時候我需要使用正則表達式捕獲某個區域中的某些段落 - 然後在每個段落上執行操作。Emacs:捕獲段落並對每個段落執行

例如,考慮恢復一個數列清單的問題:

1. Some text with a blank 
line. I want not to have that line break 
2. Some more text. Also - with 
a line break. 
3. I want to have a defun which 
will capture each numbered entry 
and then join it 

我想寫一個defun定義,這將使以前的文字像:

1. Some text with a blank line. I want not to have that line break 
2. Some more text. Also - with a line break. 
3. I want to have a defun which will capture each numbered entry and then join it 

下面是現在我的最好的嘗試:

(defun joining-lines (start end) 
    (interactive "r") 
    (save-restriction 
    (narrow-to-region start end) 
    (goto-char (point-min)) 
    (while (search-forward-regexp "\\([[:digit:]]\\. \\)\\(\\[^[:digit:]\\].*?\\)" nil t) 
      (replace-match "\\1\\,(replace-regexp-in-string " ;; here's a line break 
" " " (match-string 2))" t nil)) 
    ) 
) 

它既不工作也不報錯。

其實最好有一個獨立的defun來處理字符串。通過這種方式,可以輕鬆地將代碼擴展爲在replace-match上有多個替換。

回答

4

有兩個問題與您的代碼:

  1. 在一個正則表達式匹配期間「除了換行符什麼,」所以你.*?永遠不會有一個換行符。
  2. \,(...)正則表達式替換構造僅可交互使用。如果#1問題得到解決,您會收到錯誤(error "Invalid use of '\\' in replacement text")。以編程方式,您必須自己編寫代碼,例如:(replace-match (concat (match-string 1) (replace-regexp-in-string "\n" " " (match-string 2))))

我認爲你最好不要依賴正則表達式來完成繁重的工作。這個工作對我來說:

(defun massage-list (start end) 
    (interactive "r") 
    (save-excursion 
    (save-restriction 
     (narrow-to-region start end) 
     (goto-char start) 
     (while (progn (forward-line) (= (point) (line-beginning-position))) 
     (when (not (looking-at "^[[:digit:]]+\\.")) 
      (delete-indentation) 
      (beginning-of-line)))))) 
+0

關於'\,()'只能以交互方式提供,您可以在使用該語法運行交互式替換之後使用'C-x M-:'(repeat-complex-command),以獲得在函數中使用的等效elisp。 – phils

+0

Virtuosic代碼... – Adobe

1

嘗試類似這樣的代碼。這不是最短的,而是更直截了當的。

(defun joining-lines(start end) 
    (interactive "r") 
    (let ((newline-string "~~~")) 
    (save-restriction 
     (narrow-to-region start end) 
     (mark-whole-buffer) 
     (replace-string "\n" newline-string) 
     (goto-char start) 
     (while (re-search-forward (concat newline-string "\\([[:digit:]]+. \\)") nil t) 
     (replace-match "\n\\1" nil nil)) 
     (mark-whole-buffer) 
     (replace-string newline-string " ")))) 
+0

非常原創和方法。 +1。 – Adobe

0

下面是使用外部defun定義的解決方案:

(defun capturing-paragraphs (start end) 
    (interactive "r") 
    (save-restriction 
    (narrow-to-region start end) 
    (goto-char (point-min)) 
    (while (search-forward-regexp "^\\(^[[:digit:]]+\\.[^[:digit:]]+$\\)" nil t) (replace-match (multiple-find-replace-in-match) t nil)))) 

(defun multiple-find-replace-in-match() 
    "Returns a string based on current regex match." 
    (let (matchedText newText) 
    (setq matchedText 
     (buffer-substring-no-properties 
     (match-beginning 1) (match-end 1))) 
    (setq newText 
     (replace-regexp-in-string "\n" "" matchedText)) 
    newText)) 

它只能如果有在文中沒有數字。但是這個解決方案可以直接擴展 - 在匹配的字符串上添加新的替代品。