List Matching Lines and Delete Matching Lines in Emacs

Perm url with updates: http://xahlee.org/emacs/elisp_list_matching_lines.html

List Matching Lines and Delete Matching Lines in Emacs

Xah Lee, 2010-05-03

Emacs has a very useful command list-matching-lines. For example, open a file, then type “Alt+x list-matching-lines”. Then, give a word. Emacs will list all lines containing that word.

You can click on any matched line in the output, then emacs will put cursor at the position of the occurrence in your file.

There are also several other line processing commands for the current buffer that i use often:

list-matching-lines
delete-matching-lines
delete-non-matching-lines

sort-lines
sort-numeric-fields
reverse-region

Shortcuts and Aliases

If you use them often, you can give them a keyboard shortcut, like this:

(global-set-key (kbd "<f6>") 'list-matching-lines) ; F6 key
(global-set-key (kbd "M-8") 'list-matching-lines) ; Alt+8

For defining more complex key combos, see: How to Define Keyboard Shortcuts in Emacs.

My F key and Alt+num spots are already filled. So, i use a short command name alias instead. Define it like this:

(defalias 'lml 'list-matching-lines)
(defalias 'dml 'delete-matching-lines)

Delete Starts at Cursor Position or Text Selection

delete-matching-lines and delete-non-matching-lines starts at the line your cursor is on. So, if you want deletion to happen for the whole file, you need to move to the beginning of file first.

Also, if you have a text selection, the deletion happens in the text selection only.

Regex

All these commands uses regex to search. So, if you simply want to search plain words or phrases, and if your phrase contains any of regex characters, you need to escape them. Here some commonly used regex characters that you'll need to replace:

your search containsreplace it with
[\[
]\]
\\\
+\+
*\8
?\?
.\.

See also: common patterns in emacs regex.

Letter Case Sensitivity

In all these commands, if your search word contains upper case letters, then the search is automatically case sensitive. Otherwise, it is not case sensitive.

If you want the cases to be case sensitive (that is, literally what you gave), then you need to set the variable search-upper-case to “nil” (nil means false).

You can see the current value of a variable by the command describe-variable.

You can change a variable's value by the command set-variable.

Elisp Exercise

In recent months, i use list-matching-lines and delete-matching-lines often, in processing chat logs from Second Life and my own processed web logs. Of course, i can use unix shell tools such as “grep myPhrase myFile > outFile”, even inside emacs directly, or, i can easily write a Perl or Python script. However, the tasks that need to be done are spontaneous, and requires interactive feedback. For example, when i see the matching lines i want, i may need to call delete-matching-lines on the result to narrow down the lines i want. And this process may repeat. Calling shell to generate output requires some ten or twenty extra key press each time i need to do this. This is why emacs is so useful. (see: Text-Soup Situation and Lumberjack-Tasks.)

Here are some ideas of commands related to list-matching-line that would make emacs even more useful in my situation. They are good elisp exercises. Each of the following will take me 5 to 20 minutes to write. I'll be probably be writing them soon.

Write a list-non-matching-lines.

Often, you want to list lines by word or phrase, not regex. If your search text often contains regex chars, it'll take you extra ~3 seconds to escape them. Write a version of list-matching-lines that does not use regex. (hint: write a wrapper that calls list-matching-lines, using regexp-quote to quote the input.)

When using list-matching-lines, it would be nice if the current word under cursor will be the default search text. Or, if there's a text selection, use the text selection as default search phrase. This will save you 5 or more keystrokes or few seconds to mark and copy and paste. (hint: Emacs Lisp Idioms)

Often, i need to see what lines contains a certain word, then delete those lines. Effectively, i call list-matching-lines, then call delete-matching-lines. When i do this many times, the repetition in keystroke gets painful. It'd be nice, to have something like split-buffer-by-matching-lines, so that, it delete matching lines and show the deleted lines in a different buffer.

Popular posts from this blog

11 Years of Writing About Emacs

does md5 creates more randomness?

Google Code shutting down, future of ErgoEmacs