我经常需要使用正则表达式捕获区域中的某些段落 - 然后对每个段落执行操作。
例如,考虑恢复数字列表的问题:
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
上进行多次替换。
答案 0 :(得分:4)
您的代码存在两个问题:
.*?
将永远不会包含换行符。\,(...)
regexp替换构造仅以交互方式提供。如果问题#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))))))
答案 1 :(得分: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 " "))))
答案 2 :(得分:0)
以下是使用外部修改的解决方案:
(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))
只有在文本中没有数字时才有效。但是这个解决方案很容易扩展 - 在匹配的字符串上添加新的替换。