source - Cómo borrar las líneas de repetición en emacs.
emacs para mac (4)
En Linux, seleccione región y escriba
M-| uniq <RETURN>
El resultado sin duplicados está en el nuevo búfer.
Tengo un texto con muchas líneas, mi pregunta es ¿cómo eliminar las líneas repetidas en emacs? Uso del comando en paquetes emacs o elisp sin utils externos.
por ejemplo:
this is line a
this is line b
this is line a
para eliminar la tercera línea (igual que la primera línea)
this is line a
this is line b
Pon este código a tu .emacs:
(defun uniq-lines (beg end)
"Unique lines in region.
Called from a program, there are two arguments:
BEG and END (region to sort)."
(interactive "r")
(save-excursion
(save-restriction
(narrow-to-region beg end)
(goto-char (point-min))
(while (not (eobp))
(kill-line 1)
(yank)
(let ((next-line (point)))
(while
(re-search-forward
(format "^%s" (regexp-quote (car kill-ring))) nil t)
(replace-match "" nil nil))
(goto-char next-line))))))
Uso:
M-x uniq-lines
Si tiene Emacs 24.4 o una versión más reciente, la forma más limpia de hacerlo sería la nueva función de delete-duplicate-lines
. Tenga en cuenta que
- esto funciona en una región, no en un búfer, así que seleccione el texto deseado primero
- Mantiene el orden relativo de los originales, matando a los duplicados.
Por ejemplo, si su entrada es
test
dup
dup
one
two
one
three
one
test
five
Mx delete-duplicate-lines
lo haría
test
dup
one
two
three
five
Tiene la opción de buscar desde atrás prefijándolo con el argumento universal ( Cu
). El resultado sería entonces
dup
two
three
one
test
five
El crédito va a emacsredux.com .
Otras opciones de rotonda, que no dan el mismo resultado, están disponibles a través de Eshell:
-
sort -u
; No mantiene el orden relativo de los originales. -
uniq
; Peor necesita su entrada para ser ordenado
(defun unique-lines (start end)
"This will remove all duplicating lines in the region.
Note empty lines count as duplicates of the empy line! All empy lines are
removed sans the first one, which may be confusing!"
(interactive "r")
(let ((hash (make-hash-table :test #''equal)) (i -1))
(dolist (s (split-string (buffer-substring-no-properties start end) "$" t)
(let ((lines (make-vector (1+ i) nil)))
(maphash
(lambda (key value) (setf (aref lines value) key))
hash)
(kill-region start end)
(insert (mapconcat #''identity lines "/n"))))
(setq s ; because Emacs can''t properly
; split lines :/
(substring
s (position-if
(lambda (x)
(not (or (char-equal ?/n x) (char-equal ?/r x)))) s)))
(unless (gethash s hash)
(setf (gethash s hash) (incf i))))))
Una alternativa:
- No utilizará el historial de deshacer para almacenar coincidencias.
- En general, será más rápido (pero si busca la velocidad máxima, cree un árbol de prefijos).
- Tiene el efecto de reemplazar todos los caracteres de nueva línea anteriores, independientemente de lo que fueran con
/n
(estilo UNIX). Lo que puede ser una ventaja o una desventaja, dependiendo de su situación. - Podría hacerlo un poco mejor (más rápido), si vuelve a implementar
split-string
de manera que acepte caracteres en lugar de expresiones regulares.
Un poco más largo, pero, quizás, una variante un poco más eficiente:
(defun split-string-chars (string chars &optional omit-nulls)
(let ((separators (make-hash-table))
(last 0)
current
result)
(dolist (c chars) (setf (gethash c separators) t))
(dotimes (i (length string)
(progn
(when (< last i)
(push (substring string last i) result))
(reverse result)))
(setq current (aref string i))
(when (gethash current separators)
(when (or (and (not omit-nulls) (= (1+ last) i))
(/= last i))
(push (substring string last i) result))
(setq last (1+ i))))))
(defun unique-lines (start end)
"This will remove all duplicating lines in the region.
Note empty lines count as duplicates of the empy line! All empy lines are
removed sans the first one, which may be confusing!"
(interactive "r")
(let ((hash (make-hash-table :test #''equal)) (i -1))
(dolist (s (split-string-chars
(buffer-substring-no-properties start end) ''(?/n) t)
(let ((lines (make-vector (1+ i) nil)))
(maphash
(lambda (key value) (setf (aref lines value) key))
hash)
(kill-region start end)
(insert (mapconcat #''identity lines "/n"))))
(unless (gethash s hash)
(setf (gethash s hash) (incf i))))))