mike@peregrine.UUCP (Mike Wexler) (10/18/86)
Since I have switched from vi to EMACS, there is one thing that I missed more than anything else. The ability to perform an operation on all the lines that met a particular criteria(specified by a regular expression). For instance in vi, I could type in "/[A-Z][a-z]*/d" to delete all lines that met the specified criteria or I could type in "/\([A-Za-z][A-Za-z]*(\).*\()\)/s//\1\2". How would I do similar operations in EMACS? -- Mike Wexler (trwrb|scgvaxd)!felix!peregrine!mike (714)855-3923
wohler@sri-spam.istc.sri.com (Bill Wohler) (10/19/86)
mike, i had the same problem you did when i switch to gnuemacs, but, since gnuemacs is fully extensible, i wrote my first lisp function (no laughter from the peanut gallery, please). in addition, emacs offers a richer regular expression set than vi does. check it out! anyway, here's the function that will get you started. load it in and bind it to a key if you wish. currently you have to set the region around the section of text that you want to massage and then set your point at the beginning of the region. therefore, if you wanted to do the whole file, you could use C-x h to select the whole buffer. it works fine, but could be more elegant. for instance, it should work on the region even if you aren't at the beginning of it. if any of you can improve on it, please be sure to share your findings with us. thanks! --bw ----- 8< re-relace-region follows ----- (defun re-replace-region () nil (interactive) (setq old (read-input "Replace string: " nil)) (setq new (read-input "with: " nil)) (while (< (dot) (mark)) (re-search-forward old (+ (mark) 1) nil) (setq end (dot)) (re-search-backward old) (delete-region (dot) end) (insert new) ) )
evp@lewey.UUCP (10/19/86)
> Since I have switched from vi to EMACS, there is one thing that I missed > more than anything else. The ability to perform an operation on all > the lines that met a particular criteria(specified by a regular expression). > For instance in vi, I could type in "/[A-Z][a-z]*/d" to delete all lines > that met the specified criteria or I could type in > "/\([A-Za-z][A-Za-z]*(\).*\()\)/s//\1\2". How would I do similar operations > in EMACS? There are several answers to this question. The easiest way to do exactly what you want is to pipe the file through sed: set the mark at the top, move to the bottom of the file, then use (in GNUmacs) the "shell-command-on-region" command -- ^U ESC-|, passing the appropriate agruments to sed. The buffer will be replaced by the results of the sed. However, this isn't really in the "spirit of EMACS". When I have to do some global operation, I usually use a keyboard macro. Start the macro with ^X-(, do a single instance of the operation, then ^X-) to terminate the macro definition. Repeat it a few times with ^X-e to make sure it works right, then run it a bunch of times with ^U 999 ^X-e. If you have a search at the beginning of the macro, it will stop executing as soon as the search fails. For more interesting problems, there's the "grep" command. This allows you do a search through many files for anything that grep can find. After execution, calls to the "next-error" command (usually ^X-`) puts the cursor on the next line containing the grep expression, in whatever file. If that line is one that needs to be changed, you can easily generate a keyboard macro that does the operation then moves to the next instance. Your last example can be performed almost verbatim with the GNUmacs "query-replace-regexp" command, which I bind to ESC-Q. -- Ed Post {hplabs,voder,pyramid}!lewey!evp American Information Technology 10201 Torre Ave. Cupertino CA 95014 (408)252-8713
jr@CC5.BBN.COM (John Robinson) (10/20/86)
Then again, you could use this built-in function in the loop: replace-regexp: Replace things after point matching REGEXP with TO-STRING. Preserve case in each match if case-replace and case-fold-search are non-nil and REGEXP has no uppercase letters. Third arg DELIMITED (prefix arg if interactive) non-nil means replace only matches surrounded by word boundaries. In TO-STRING, \& means insert what matched REGEXP, and \<n> means insert what matched <n>th \(...\) in REGEXP. /jr
phr@ernie.Berkeley.EDU (Paul Rubin) (10/20/86)
In article <403@lewey.UUCP> evp@lewey.UUCP (Ed Post) writes: >> Since I have switched from vi to EMACS, there is one thing that I missed >> more than anything else. The ability to perform an operation on all >> the lines that met a particular criteria(specified by a regular expression). >> For instance in vi, I could type in "/[A-Z][a-z]*/d" to delete all lines >> that met the specified criteria or I could type in >> "/\([A-Za-z][A-Za-z]*(\).*\()\)/s//\1\2". How would I do similar operations >> in EMACS? > >There are several answers to this question. The easiest way to do >exactly what you want is to pipe the file through sed... Ugh!! The first thing to try when figuring out things like this is the Apropos command. You can also get more detailed documentation from the Emacs Info file: type C-h I, then look through the Command Index and Concept Index nodes til you find what you want. In this case, you get the following descriptions. You can also bring in the Lisp source for these commands to see how they work or to modify them to do anything you want on matching (non-matching, etc.) lines. File: emacs Node: Other Repeating Search, Prev: Replace, Up: Search Other Search-and-Loop Commands ============================== Here are some other commands that find matches for a regular expression. They all operate from point to the end of the buffer. `M-x list-matching-lines' Print each line that follows point and contains a match for the specified regexp. A numeric argument specifies the number of context lines to print before and after each matching line; the default is none. `M-x count-matches' Print the number of matches following point for the specified regexp. `M-x delete-non-matching-lines' Delete each line that follows point and does not contain a match for the specified regexp. `M-x delete-matching-lines' Delete each line that follows point and contains a match for the specified regexp.
wunder@hpcea.HP.COM (Walter Underwood) (10/21/86)
> Since I have switched from vi to EMACS, there is one thing that I missed > more than anything else. The ability to perform an operation on all > the lines that met a particular criteria(specified by a regular expression). > > Mike Wexler Just use keyboard macros. Start the macro, do a regex search, do the action, and close the macro. Give it a very large arg (type ^U ten times) and then execute the macro. Voila! Your buffer has been munged! I had the same problem when converting from vi, but I find that keyboard macros are actually more powerful than regular expressions, and easier to specify. They are also much easier to teach to a novice. wunderwood wunder@hplabs