|Subject:||Re: Emacs equivalent of the ":g" command in vi|
|Date:||Fri, 22 Jul 2011 16:27:44 -0400|
|User-agent:||Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:126.96.36.199) Gecko/20110414 Thunderbird/3.1.10|
On 7/22/2011 4:42 AM, C K Kashyap wrote:
I looked for the same thing ages ago when I switched from vi to emacs. Eventually I figured out that:
: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'.)
An Emacs macro is a series of emacs commands that you can replay. You use C-( and C-) as follows to create a macro:
C-(Then, whenever you type C-x e, Emacs will replay the commands.
At this point, you're probably wondering how this can substitute for vi's g//. Simple. Just start your macro off with a regular _expression_ search, do whatever you want, and then replay it multiple times with:
C-u count C-x eSpecify a large enough repeat count, and you can make your macro apply to the whole file.
For example, to delete each line of a buffer if the line matches a regular _expression_, you'd define the macro with:
C-( ;; Begin recording macroThen you'd execute the macro with:
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.
For example, if I have a file of lines of the format:
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:
: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-u 10000 C-x eIt will stop as soon as it runs out of matching lines.
The point is that the operations you can repeat this way are limited only by your imagination.
There's a variant of this that I use frequently. I often find that a non-emacs application wants me to type lots of information into individual fields of an input screen. It's a pain to have to type all that data, especially when I have that data in a text file. In emacs I can organize the data into the same order as the input fields in the application, putting each field's data on a separate line of the emacs buffer. Then I do the following in emacs:
;; Begin recording macroOnce I've defined that macro, I can repeatedly type:
;; This is not an Emacs command. It tells the window managerAt that point, I repeatedly type:
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.
If you should want to save a macro you've created this way so you can use it in future Emacs sessions:
Open your .emacs file: C-x C-f ~/.emacs
P.S. - Interesting side-note. Did you know that the ed command:Mark Rosenthal
is where the name "grep" came from? In ed and ex, the "g" means do a global search for the immediately following regular _expression_, and apply the operation to every matching line. One such operation is "p" meaning "print". Using "re" as shorthand for "regular _expression_", the ed command to print every line that matches a particular regular _expression_ is:
|[Prev in Thread]||Current Thread||[Next in Thread]|