Hi,Could someone please tell me how I could go about something like this -I need to perform a certain action (such as delete the line) on each line of a buffer if the line matches a regular expression. In vim, we can use the :g command for this.Regards,Kashyap
:g/regular expression/operationreflects an 'ed' mindset, and that an Emacs macro with a repeat count is actually far more powerful . (In case you're wondering what 'ed' is, it was the original, line-oriented, Unix editor. 'vi' was Bill Joy's visual mode version of 'ex', which was his enhanced version of 'ed'.)
C-(Then, whenever you type C-x e, Emacs will replay the commands.
type any commands you want Emacs to remember
C-)
C-u count C-x eSpecify a large enough repeat count, and you can make your macro apply to the whole file.
C-( ;; Begin recording macroThen you'd execute the macro with:
C-M-s regexp ;; Search for regular expression
C-a ;; Go to beginning of line
C-k ;; Kill one line by typing C-k twice
C-k ;;
C-) ;; End recording macro
C-u 10000 C-x eOf course, there's an easier way to delete lines that match a regular expression:
M-x delete-matching-linesBut you described the general problem as needing to perform a certain action on each line of a buffer if the line matches a regular expression. And the approach of defining a macro to do what you want and then executing it with a large repeat count gives you a general purpose mechanism to do arbitrary operations rather than just delete the line.
zip,street address,city,state,phone,nameThat I wanted to rearrange to:
name,phone,street address,city,state,zipI could run:
M-x replace-regexpwhich is the equivalent of vi's:
^\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\)$
\6,\5,\2,\3,\4,\1
:g/^\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\)$/s//\6,\5,\2,\3,\4,\1/gBut making sure you've got that regular expression right can be tricky. It can be much easier to just do it with emacs commands applied to a single line. Although the following is difficult to read, I think if you try it out you'll find it pretty straightforward. First fill an emacs buffer with lots of lines of the form:
name,phone,street address,city,state,zipThen type these emacs keystrokes (omitting the comments):
;; Begin recording macroReplay it 10,000 times with:
C-(
;; Narrow the buffer to the current line:
C-SPC C-n C-x n n M-<
;; Move the part after the fifth ","
;; to the beginning of the line
C-s , C-s C-s C-s C-s C-b C-k C-a C-y , C-a C-d
;; Move the part that's now after the fifth ","
;; to the second comma-delimited position
C-s , 4*C-s C-b C-k C-a M-f C-y
;; Move the third comma-delimited part to the end
M-d C-e C-y
;; Move forward over the newline to the next line
C-f
;; Widen so you can see the whole buffer
C-x n w
;; End recording macro
C-)
C-u 10000 C-x eIt will stop as soon as it runs out of matching lines.
;; Begin recording macroOnce I've defined that macro, I can repeatedly type:
C-(
;; Mark region from beginning to end of line
C-a C-SPC C-e
;; Copy region so it can be pasted into another application
C-w
;; Move forward over the newline to the next line
C-f
;; End recording macro
C-)
;; This is not an Emacs command. It tells the window managerAt that point, I repeatedly type:
;; to give keyboard focus to the other application.
ALT-TAB
;; Paste into the input field
C-v
;; Move focus to the next input field
TAB
;; Give keyboard focus to Emacs.
ALT-TAB
;; Repeat the macro, which copies the next line.
C-x e
C-x e ALT-TAB C-v TAB ALT-TABWhile it's not fully automated, If I've got lots of data that has to be entered through a GUI interface, it makes things go a whole lot faster.
Open your .emacs file: C-x C-f ~/.emacs
Give it a name by with: M-x name-last-kbd-macro
Insert it into your .emacs with: M-x insert-kbd-macro
Save your .emacs file: C-x C-s
P.S. - Interesting side-note. Did you know that the ed command:Mark Rosenthal
mbr@arlsoft.com