JohnBeckett (talk | contribs) m (Power of moved to Power of g: Old title was 'Power of :g' (but wiki doesn't like colon); have kept the quirky title because it's nice) |
JohnBeckett (talk | contribs) (Undo revision 37152 by 67.180.48.92 (talk) What is wrong?) |
||
(29 intermediate revisions by 15 users not shown) | |||
Line 1: | Line 1: | ||
+ | {{TipImported |
||
− | {{review}} |
||
− | {{Tip |
||
|id=227 |
|id=227 |
||
+ | |previous=225 |
||
− | |title=Power of |
||
+ | |next=228 |
||
− | |created=March 24, 2002 3:15 |
||
+ | |created=2002 |
||
|complexity=intermediate |
|complexity=intermediate |
||
|author=Arun Easi |
|author=Arun Easi |
||
− | |version= |
+ | |version=6.0 |
|rating=900/308 |
|rating=900/308 |
||
+ | |category1=Searching |
||
− | |text= |
||
+ | |category2= |
||
− | :g is something very old and which is very powerful. I just wanted to illustrate the use of it |
||
− | |||
− | with some examples. Hope, it will be useful for someone. |
||
− | |||
− | |||
− | |||
− | Brief explanation for ":g" |
||
− | |||
− | ------------------------- |
||
− | |||
− | Syntax is: |
||
− | |||
− | :[range]:g/<pattern>/[cmd] |
||
− | |||
− | You can think the working as, for the range (default whole file), execute |
||
− | |||
− | the colon command(ex) "cmd" for the lines matching <pattern>. Also, for all |
||
− | |||
− | lines that matched the pattern, "." is set to that particular line (for |
||
− | |||
− | certain commands if line is not specified "." (current line) is assumed). |
||
− | |||
− | |||
− | |||
− | Some examples |
||
− | |||
− | ------------- |
||
− | |||
− | Display context (5 lines) for all occurences of a pattern |
||
− | |||
− | :g/<pattern>/z#.5 |
||
− | |||
− | :g/<pattern>/z#.5|echo "==========" |
||
− | |||
− | << same as first, but with some beautification >> |
||
− | |||
− | Delete all lines matching a pattern |
||
− | |||
− | :g/<pattern>/d |
||
− | |||
− | Delete all blank lines (just an example for above) |
||
− | |||
− | :g/^\s*$/d |
||
− | |||
− | Double space the file |
||
− | |||
− | :g/^/pu =\"\n\" |
||
− | |||
− | :g/^/pu _ |
||
− | |||
− | << the above one also works >> |
||
− | |||
− | Copy all lines matching a pattern to end of file |
||
− | |||
− | :g/<pattern>/t$ |
||
− | |||
− | Yank all lines matching a pattern to register 'a' |
||
− | |||
− | 0"ay0:g/<pattern>/y A |
||
− | |||
− | Increment the number items from current line to end-of-document by one |
||
− | |||
− | :.,$g/^\d/exe "normal! \<c-a>" |
||
− | |||
− | Comment (C) lines containing "DEBUG" statements |
||
− | |||
− | g/^\s*DEBUG/exe "norm! I/* \<Esc>A */\<Esc>" |
||
− | |||
− | A Reverse lookup for records |
||
− | |||
− | (eg: An address book, with Name on start-of-line and fields after a space) |
||
− | |||
− | :g/<patern>?^\w?p "if only name is interested |
||
− | |||
− | :g/<patern>/ka|?^\w?p|'ap "if name and the lookup-line is interested |
||
− | |||
− | :g/<patern>/?^\w?|+,/^[^ ]/-1p "if entire record is interested |
||
− | |||
− | Reverse a file (just to show the power of 'g') |
||
− | |||
− | :g/^/m0 |
||
− | |||
− | |||
− | |||
− | Foot note 1: use :v to negate the search pattern |
||
− | |||
− | Foot note 2: Some explanation of commonly used commands with :g |
||
− | |||
− | :2,8co15 => Copy lines 2 through 8 after line 15 |
||
− | |||
− | :4,15t$ => Copy linesa 4 through 15 towards end of document (t == co) |
||
− | |||
− | :-t$ => Copy previous line to end of document |
||
− | |||
− | :m0 => Move current line to the top of the document |
||
− | |||
− | :.,+3m$-1 => Move current line through cur-line+3 to the last but one line |
||
− | |||
− | of the document |
||
− | |||
− | Foot note 3: Commands used with :g are ex commands, so a help search should |
||
− | |||
− | be, |
||
− | |||
− | :help :<help-topic> |
||
− | |||
− | eg. :help :k |
||
− | |||
− | |||
}} |
}} |
||
+ | The global command <code>:g</code> is very useful. Here are some examples showing the power of <code>:g</code>. |
||
+ | ==Brief explanation of <code>:g</code>== |
||
− | == Comments == |
||
+ | <pre> |
||
− | Thanx Karma for extending my g// knowledge |
||
+ | :[range]g/<pattern>/cmd |
||
+ | </pre> |
||
+ | This will act on the specified ''[range]'' (default whole file), by executing the Ex command ''cmd'' (An Ex command is one starting with a colon (':')) for each line matching ''<pattern>''. Before executing ''cmd'', "." is set to the current line. |
||
− | Here's a very useful g// for day to day use |
||
+ | ==Examples== |
||
− | :'a,'bg/pattern/s/pattern2/string3/gi |
||
+ | Display context (5 lines) for all occurrences of a pattern. |
||
+ | <pre> |
||
+ | :g/<pattern>/z#.5 |
||
+ | " Same, but with some beautification. |
||
+ | :g/<pattern>/z#.5|echo "==========" |
||
+ | </pre> |
||
+ | Delete all lines matching a pattern. |
||
− | zzapper |
||
+ | <pre> |
||
+ | :g/<pattern>/d |
||
+ | </pre> |
||
+ | Delete all lines that do '''not''' match a pattern. |
||
− | david--AT--tvis.co.uk |
||
+ | <pre> |
||
− | , March 28, 2002 7:10 |
||
+ | :g!/<pattern>/d |
||
− | ---- |
||
+ | </pre> |
||
− | g WITH CONFIRM c |
||
+ | Delete all blank lines (<code>^</code> is start of line; <code>\s*</code> is zero or more whitespace characters; <code>$</code> is end of line) |
||
− | Here's something very curious: |
||
+ | <pre> |
||
+ | :g/^\s*$/d |
||
+ | </pre> |
||
+ | Double space the file (<code>^</code> is start of line which matches each line). |
||
− | :%s/foo/bar/gc |
||
+ | <pre> |
||
− | is of course a substitution effective for the entire file |
||
+ | :g/^/pu =\"\n\" |
||
− | with confirm on each occurrence of "foo" |
||
+ | " Alternative (:put inserts nothing from the blackhole register) |
||
− | with the option of quitting at any point. |
||
+ | :g/^/pu _ |
||
+ | </pre> |
||
+ | Copy all lines matching a pattern to end of file. |
||
− | However, using something similar, |
||
+ | <pre> |
||
+ | :g/<pattern>/t$ |
||
+ | </pre> |
||
+ | Move all lines matching a pattern to end of file. |
||
− | :g/foo/s//bar/gc |
||
+ | <pre> |
||
− | using the global g to effect the entire file -- |
||
+ | :g/<pattern>/m$ |
||
− | does NOT allow quitting at any point |
||
+ | </pre> |
||
− | (even with the use of <ESC>). |
||
+ | Copy all lines matching a pattern to register 'a'. |
||
− | If there are hundreds of "foo" -- it's an important fine point... |
||
+ | <pre> |
||
+ | qaq:g/<pattern>/y A |
||
+ | </pre> |
||
+ | :''Explanation'' <code>qaq</code> is a trick to clear register <code>a</code> (<code>qa</code> starts recording a macro to register <code>a</code>, then <code>q</code> stops recording, leaving <code>a</code> empty). <code>y A</code> is an Ex command ({{help|:y}}). It yanks the current line into register <code>A</code> (append to register <code>a</code>). |
||
+ | Increment each number at the start of a line, from the current line to end-of-file, by one (the exclamation mark in <code>:normal!</code> means this will work even if Ctrl-A has been mapped to perform a function other than its default of incrementing a number). |
||
− | Invite further comments... |
||
+ | <pre> |
||
+ | :.,$g/^\d/exe "normal! \<C-A>" |
||
+ | </pre> |
||
+ | Comment lines containing "DEBUG" statements in a C program. |
||
− | Hal Atherton |
||
+ | <pre> |
||
− | , April 23, 2002 10:12 |
||
+ | " using :normal |
||
− | ---- |
||
+ | g/^\s*DEBUG/exe "norm! I/* \<Esc>A */\<Esc>" |
||
− | g/foo/s//bar/gc => run the command s//bar/gc for each of the line |
||
+ | " using :substituting |
||
− | matching foo. It is like running multiple "s//" commands (Hence |
||
+ | g/^\s*DEBUG/s!.*!/* & */! |
||
− | you have to press q for each of the invocation). The |
||
+ | </pre> |
||
− | g in "s///gc" does not imply entire file, it just implies all occurence |
||
− | on a line (or else, it would have substituted only the first) |
||
+ | Reverse lookup for records (say an address book, with Name at start-of-line and fields after a space). |
||
− | Arun Easi |
||
+ | <pre> |
||
− | , April 23, 2002 23:33 |
||
+ | :g/<pattern>/?^\w?p "if only name is interesting |
||
− | ---- |
||
+ | :g/<pattern>/ka|?^\w?p|'ap "if name and the lookup-line is interesting |
||
− | Here is one that deletes every other line (adjusting double spaced files): |
||
+ | :g/<pattern>/?^\w?|+,/^[^ ]/-1p "if entire record is interesting |
||
+ | </pre> |
||
+ | :''Explanation'' See {{help|:range}} for the meaning of the constructs in the <code><nowiki>[cmd]</nowiki></code> portion of the <code>:g</code> commands. |
||
+ | Reverse a file (just to show the ''power of g''). |
||
− | :g/.*/norm jdd |
||
+ | <pre> |
||
+ | :g/^/m0 |
||
+ | </pre> |
||
+ | :''Explanation'' According to {{help|multi-repeat}}, <code>:g</code> and its cousin <code>:v</code> work in a two-pass manner. The first pass of <code>:g</code> marks every line matching <code>{pattern}</code>, while the second pass (apparently performed starting at the file's beginning and proceeding to the end) performs the <code><nowiki>[cmd]</nowiki></code>. The above use of <code>:g</code> takes advantage of the order the lines are processed in (which is probably okay, though probably not technically guaranteed). It works by first marking every line, then moving the first marked line to the top of the file, then moving the second to the top of the file (above the line moved previously), then the third marked line (again above the previously moved line), and so on until the last line in the file is moved to the top, effectively reversing the file. Note that if <code>:g</code> processed lines in any order other than from top to bottom, this command would not work. |
||
+ | Add text to the end of a line that begins with a certain string. |
||
− | dyang--AT--entropia.com |
||
+ | <pre> |
||
− | , May 30, 2002 9:04 |
||
+ | :g/^pattern/s/$/mytext |
||
− | ---- |
||
+ | </pre> |
||
− | This can be done much simpler: |
||
+ | ==Notes== |
||
− | :%norm jdd |
||
+ | Use <code>:v</code> to reVerse the sense of the search pattern. Example: Delete all lines ''not'' matching ''pattern'': |
||
− | |||
+ | <pre> |
||
− | pagaltzis()gmx_de |
||
− | , August 6, 2002 15:12 |
||
− | ---- |
||
− | Another cool g feature is to count the number of lines matching /regexp/ |
||
− | |||
− | let x=0 | g/regexp/let x=x+1 |
||
− | echo x |
||
− | |||
− | Great, if you are editing data files. |
||
− | |||
− | Regards |
||
− | Mike |
||
− | |||
− | mra--AT--frogne.dk |
||
− | , February 10, 2003 4:49 |
||
− | ---- |
||
− | Reverse all the lines in a file: |
||
− | |||
− | :g/^/m0 |
||
− | |||
− | I have found that useful . . . honest! |
||
− | |||
− | PK |
||
− | |||
− | |||
− | setanta5--AT--excite.com |
||
− | , March 27, 2003 2:14 |
||
− | ---- |
||
− | Can I do something like this using ":g" (or anything else) |
||
− | |||
− | I have a file which contains following kind of lines |
||
− | |||
− | abc123=1,2,3 |
||
− | bcd123=100,200,300 |
||
− | abcb123=1,3,4 |
||
− | |||
− | I want to convert this to following |
||
− | |||
− | abc123=1,abc,2,abc,3,abc |
||
− | bcd123=100,bcd,200,bcd,300,bcd |
||
− | abcb123=1,abcb,3,abcb,4,abcb |
||
− | |||
− | Basically I want to replace each comma in a line with first few letters, which are coming before 123, of that line surrounded by 2 commas. |
||
− | |||
− | kkgahlot--AT--yahoo.com |
||
− | , September 3, 2003 5:06 |
||
− | ---- |
||
− | To answer kkgahlot's question: |
||
− | |||
− | global // execute "s/\\([=,][^,]*\\)/\\1, " . matchstr (getline ("."), "^.\\{-}\\(123\\)\\--AT--=") . "/g" |
||
− | |||
− | |||
− | To make the whole thing a little more transparent some explanations (from the inside out): |
||
− | |||
− | We want to execute on each line a command like |
||
− | |||
− | s/\([=,][^,]*\)/\1, abc/g |
||
− | |||
− | for each line, but abc gets changed on each line. |
||
− | |||
− | The function |
||
− | |||
− | matchstr (getline ("."), "^.\\{-}\\(123\\)\\--AT--=") |
||
− | |||
− | returns the string that matches the pattern /^.\{-}\(123)\--AT--=/ on the current line. In the given examples this is the text preceding 123= at the beginning of the line. Depending on the actual requierements, a simpler expression like /^[a-z]*/ could work too. |
||
− | |||
− | The command |
||
− | |||
− | execute "s/\\([=,][^,]*\\)/\\1, " . matchstr (getline ("."), "^.\\{-}\\(123\\)\\--AT--=") . "/g" |
||
− | |||
− | assembles the desired substitute command for the current line by joining some static text with the return value of the matchstr function and then executes it. |
||
− | |||
− | As execute works only on the current line, the command |
||
− | |||
− | global // execute ... |
||
− | |||
− | applies it to all line. If only certain lines should be proecessed replace // with some other pattern. |
||
− | |||
− | |||
− | |||
− | '''Anonymous''' |
||
− | , September 3, 2003 12:45 |
||
− | ---- |
||
− | Reverting lines in a file can also be done via |
||
− | :%!tac |
||
− | |||
− | instead of tac, you can also use sort, xxd, xxd -r, cut, your-own-filter |
||
− | |||
− | utzb--AT--gmx.de |
||
− | , November 21, 2003 10:39 |
||
− | ---- |
||
− | too bad :g does not have a /c parameter for confirmed execution of ex commands. Something like the /c used in :<range>s/<PAT>/<REPL>/c for replacing only confirmed pattern locations. |
||
− | |||
− | or does it ?? |
||
− | |||
− | '''Anonymous''' |
||
− | , March 29, 2004 7:18 |
||
− | ---- |
||
− | I just want to add that the :g command in vi/ed is the basis for the name for the Unix grep command, i.e. Global Regular Expression Print. The "Print" part described the default behaviour of :g when no command was given. Obviously this behaviour was more useful when using ed. |
||
− | |||
− | jdimpson--AT--yahoo.com |
||
− | , April 14, 2004 10:06 |
||
− | ---- |
||
− | Thank you for the tip |
||
− | |||
− | bsjawle--AT--hotmail.com |
||
− | , August 16, 2004 23:55 |
||
− | ---- |
||
− | Thanks for reminding about the power of :g! I used to use it back when there was only "vi". But together with vim it becomes so much stronger. Now, if someone could explain: |
||
− | |||
− | :g/^/pu _ |
||
− | |||
− | I guess I should know and I guess it's an RTFM thinngy. But anyway. =) |
||
− | /PEZ |
||
− | |||
− | pez--AT--pezius.com |
||
− | , December 16, 2004 4:33 |
||
− | ---- |
||
− | The command |
||
− | |||
− | :g/^/pu _ |
||
− | |||
− | is the global command with ^ as search pattern. The ^ matches the beginning of a line and |
||
− | therefore each line of the file is a match. |
||
− | The pu _ command is the :put command putting the contents of the _ blackhole register |
||
− | after the current line followed by a newline. The blackhole register _ never contains anything |
||
− | and therefore it can be used to insert an empty line. This is like doing cp /dev/nul empty.file |
||
− | to create an empty file. |
||
− | What the entire command does is putting an empty line after each line of the file. |
||
− | |||
− | |||
− | |||
− | jpaulus--AT--fNrOeeSnPeAt.dMe - NOSPAM |
||
− | , February 22, 2005 12:15 |
||
− | ---- |
||
− | The above note contains a typo. cp /dev/nul empty.file is wrong. |
||
− | cp /dev/null empty.file is right. |
||
− | Doing touch empty.file is another way to create an empty file if it does not exist yet. |
||
− | |||
− | |||
− | |||
− | '''Anonymous''' |
||
− | , February 22, 2005 12:32 |
||
− | ---- |
||
− | I work a lot with coordinate lists that have the following format: |
||
− | |||
− | XXXXXXX.XXXXXX YYYYYYY.YYYYYY |
||
− | |||
− | these lists can be extremely long. Sometimes, the same coordinate appears twice or more times, how can I delete multiple occurences? |
||
− | |||
− | '''Anonymous''' |
||
− | , December 22, 2005 2:02 |
||
− | ---- |
||
− | how can you globally delete lines 'not matching' a pattern |
||
− | |||
− | '''Anonymous''' |
||
− | , March 17, 2006 12:41 |
||
− | ---- |
||
− | Mention should also be made of :g's cousin, :v which is the same except it runs the command on every line that *does not* match the pattern. |
||
− | |||
− | So to delete all the lines that do not match a particular pattern you do |
||
:v/pattern/d |
:v/pattern/d |
||
+ | </pre> |
||
− | jonathantan86--AT--hotmail.com |
||
− | , March 18, 2006 2:29 |
||
---- |
---- |
||
+ | Some explanation of commands commonly used with <code>:g</code> |
||
− | Is there way I can use :g to search a pattern and delete from that pattern to the end of line instead of deleting the whole line. |
||
+ | <pre> |
||
+ | :2,8co15 "copy lines 2 through 8 after line 15 |
||
+ | :4,15t$ "copy lines 4 through 15 to end of document (t == co) |
||
+ | :-t$ "copy previous line to end of document |
||
+ | :m0 "move current line to line 0 (i.e. the top of the document) |
||
+ | :.,+3m$-1 "current line through current+3 are moved to the lastLine-1 (i.e. next to last) |
||
+ | </pre> |
||
− | ra_v_na--AT--rediffmail.com |
||
− | , March 24, 2006 9:21 |
||
---- |
---- |
||
+ | Since commands used with :g are Ex commands, searching for help should include the colon. |
||
− | :g/<pattern>7d does not work ? Is there any way to accompolish this. I want to delete more than 1 lines based on a pattern |
||
+ | <pre> |
||
+ | :help :<help-topic> |
||
+ | :help :k "example |
||
+ | </pre> |
||
+ | ==References== |
||
− | amjain.gzb--AT--gmail.com |
||
+ | *{{help|ex-cmd-index}} provides a list of Ex commands. |
||
− | , April 4, 2006 6:55 |
||
+ | *{{help|10.4}} is the section of the user manual discussing the :global command. |
||
− | ---- |
||
+ | *{{help|multi-repeat}} talks about both the :g and :v commands. |
||
− | Run a macro on a matching lines |
||
− | (example assuming a macro recorded as 'q'): |
||
− | :g/<pattern>/normal --AT--q |
||
− | g and normal combined is cool. |
||
+ | ==Comments== |
||
+ | Over a range defined by marks ''a'' and ''b'', operate on each line containing ''pattern''. The operation is to replace each ''pattern2'' with ''string''. |
||
+ | <pre> |
||
+ | :'a,'bg/pattern/s/pattern2/string/gi |
||
+ | </pre> |
||
− | noah--AT--noah.org |
||
− | , April 20, 2006 15:20 |
||
---- |
---- |
||
+ | Run a macro on matching lines (example assuming a macro recorded as 'q'): |
||
− | A co-worker keeps asking me how to globally delete lines that do not match a pattern. Very useful. |
||
+ | <pre> |
||
− | |||
+ | :g/<pattern>/normal @q |
||
− | To delete all things matching "pattern", you would do |
||
+ | </pre> |
||
− | :%g/pattern/d |
||
− | |||
− | So to delete the lines that do not match, you negate the pattern using "!", like this |
||
− | :%g!/pattern/d |
||
− | |||
− | This is very useful when trying to make sense of huge logfiles, especially when used with the "or" operator. If I wanted to open a logfile and remove everything that did not match "steve", "May 2", or "addition" (sometimes you're looking for multiple things in a logfile, you get the idea), I would do something like this |
||
− | :%g!/steve\|May 2\|addition/d |
||
− | kaan--AT--erdener.org |
||
− | , May 2, 2006 18:41 |
||
---- |
---- |
||
+ | To delete (subsequent) duplicate lines from a file: |
||
− | Regarding the post above by <amjain.gzb--AT--gmail.com>: |
||
+ | <pre> |
||
− | You should be able to do something like this: |
||
+ | :g/^\(.*\)\(\r\?\n\1\)\+$/d |
||
− | :g/<pattern>/ norm d7d |
||
+ | :%!uniq |
||
+ | </pre> |
||
+ | To just view the duplicates use: |
||
− | '''Anonymous''' |
||
+ | <pre> |
||
− | , June 2, 2006 16:12 |
||
+ | /^\(.*\)\(\r\?\n\1\)\+$ |
||
− | ---- |
||
+ | </pre> |
||
− | To delete (subsequent) duplicate lines from a file: |
||
− | :g/^\(.*\)\(\r\?\n\1\)\+$/d |
||
− | To just view the duplicates use: |
||
− | /^\(.*\)\(\r\?\n\1\)\+$ |
||
− | |||
− | -Rob (phxrider\at\gmail) |
||
− | |||
− | Anonymous |
||
− | , July 13, 2006 12:39 |
||
---- |
---- |
||
+ | Compress multiple occurrences of blank lines into a single blank line |
||
− | Hi! |
||
+ | <pre> |
||
+ | :v/./,/./-j |
||
+ | </pre> |
||
+ | Use <code>:helpgrep '\/,\/' *.txt</code> for an explanation. |
||
− | Сan somebody help me? |
||
+ | I'll break down this incredible collapse-multiple-blank-lines command for everyone, now that I finally figured out how it works. |
||
− | How can I copy a result of the command :g/pattern/# from the command-line window? |
||
+ | First, however, I'll rewrite it this way to illustrate that some of those slashes have totally different meaning than others: |
||
− | ruslan.gordeev--AT--gmail.com |
||
+ | <pre> |
||
− | , July 18, 2006 2:29 |
||
+ | :v_._,/./-1join |
||
− | ---- |
||
+ | </pre> |
||
− | you can use |
||
− | :g/^/exec "s/^/".strpart(line(".")." ",0,4) |
||
− | (for inserting line numbers) |
||
− | and then |
||
− | :v/<patern>/d |
||
− | ...output is desired i think :) ...but it's not very beautiful way :o) |
||
− | then just twice u (undo) to get original content |
||
+ | Note that to delimit expressions like these, just about any symbol can be used in place of the typical slashes... in this case, I used underscores. What we have is an inverse search (:v, same as :g!) for a dot ('.') which means anything except a newline. So this will match empty lines and proceed to execute [command] on each of them. |
||
− | uzivatel--AT--szm.sk |
||
+ | <pre> |
||
− | , July 24, 2006 4:19 |
||
+ | :v_._[command] |
||
− | ---- |
||
+ | </pre> |
||
− | Can the search pattern matches also give the number of matches found in the file. |
||
− | Let's say i execute the command similar to |
||
+ | The remaining [command] is this, which is a fancy join command, abbreviated earlier as just 'j'. |
||
− | :/<search_pattern> |
||
+ | <pre> |
||
− | In the results while it is searching can it print, the number of matches found for that pattern. |
||
+ | ,/./-1join |
||
− | say "30 lines 50 words 100 characters matched" be printed at the command area ? |
||
+ | </pre> |
||
+ | The comma tells it to work with a range of lines: |
||
+ | <pre> |
||
+ | :help :, |
||
+ | </pre> |
||
+ | With nothing before the comma, the range begins at the cursor, which is where that first blank line was. The end of the range is specified by a search, which to my knowledge actually does require slashes. The slash and dot mean to search for anything (again), which matches the nearest non-empty line and offsets by {offset} lines. |
||
+ | <pre> |
||
+ | /./{offset} |
||
+ | </pre> |
||
+ | The {offset} here is -1, meaning one line above. In the original command we just saw a minus sign, to which vim assumes a count of 1 by default, so it did the same thing as how I've rewritten it, but simply with one character fewer to type. |
||
− | msrinirao[at]gmail[dot]com |
||
+ | <pre> |
||
− | , July 26, 2006 4:18 |
||
+ | /./-1 |
||
− | ---- |
||
+ | </pre> |
||
− | Increment the number items from current line to end-of-document by one |
||
− | :.,$g/^\d/exe "normal! \<c-a>" |
||
+ | There is a caveat about join that makes this trick possible. If you specify a range of only one line to "join", it will do nothing. For example, this command tells vim to join into one line all lines from 5 to 5, which does nothing: |
||
− | Thanks for the above tip..but i am bit curious to know how it works. |
||
+ | <pre> |
||
− | can any one explain me how it's able to increment that means what <c-a> will represent??? |
||
+ | :5,5join |
||
+ | </pre> |
||
+ | In this case, any time you have more than one empty line (the case of interest), the join will see a range greater than one and join them together. For all single empty lines, join will leave it alone. |
||
− | k.nagakiran--AT--gmail.com |
||
− | , August 20, 2006 23:41 |
||
− | ---- |
||
− | <C-A> |
||
− | means press Ctrl + A keys on keyboard |
||
− | it increments number under cursor in normal mode |
||
− | ...but it doesn't work if u have mapped this key (e.g. by vim |
||
− | under windows where are these keys (<C-V>,<C-S>,... - see output of :map command) |
||
− | mapped after installing) |
||
+ | There's no good way use a delete command with :v/./ because you have to delete one line for every empty line you find. Join turned out to be the answer. |
||
− | then u can use |
||
− | :unmap <C-A> to remove this mapping temporally (it will work again after new start of vim or command :source <your_PATH>_vimrc) |
||
− | and then try it in normal mode |
||
+ | This command only merges truly "empty" lines... if any lines contain spaces and/or tabs, they will not be collapsed. To make sure you kill those lines, try this: |
||
+ | <pre> |
||
+ | :v/^[^ \t]\+$/,/^[^ \t]\+$/-j |
||
+ | </pre> |
||
+ | Or, to just clean such lines up first, |
||
− | uzivatel--AT--szm.sk |
||
+ | <pre> |
||
− | , August 23, 2006 1:31 |
||
− | ---- |
||
− | Is there a way to delete from beginning of line (^) up to <pattern> on a line for all lines in a file? |
||
− | |||
− | OR |
||
− | |||
− | delete X characters on each line for Y number of lines? |
||
− | |||
− | Thanks! |
||
− | |||
− | memyselfandi--AT--graffiti.net |
||
− | , August 28, 2006 15:45 |
||
− | ---- |
||
− | to everyone asking "is there a way to match ....... ": |
||
− | The answer is probably yes. Vim uses regular expressions, which are |
||
− | a very powerful way of finding patterns. They take some work to get |
||
− | good at (i've only been using them for 2 weeks), but any time you put |
||
− | into them will be greatly rewarded! And, since you are a Vim user, |
||
− | you are obviously used to at least one power tool that takes some |
||
− | learning but greatly improves your productivity. |
||
− | |||
− | The best way imo to learn regular expressions is |
||
− | 1) get a simple cheat sheet for Vim regular expressions |
||
− | 2) look through a list of examples, eg: |
||
− | http://www.rayninfo.co.uk/vimtips.html |
||
− | 3) any time you're doing a repetitive editing task like deleting all the |
||
− | comment characters from the beginning of a code block, think of |
||
− | how a regular expression might make the job easier & figure out |
||
− | how to do it. |
||
− | |||
− | the Vim manual has lots of stuff on regular expressions, but it's not the |
||
− | easisest to follow. here are some of the help pages: |
||
− | |||
− | bare basics on searching: chapter 3, section 9 (usr_03.txt) |
||
− | a little more comprehensive: chapter 27 (usr_27.txt) |
||
− | pretty in-depth: regexp & search commands (pattern.txt) |
||
− | |||
− | to ra_v_na: |
||
− | |||
− | i'm not sure about :g but :s will work. |
||
− | |||
− | :%s/\(pattern\).*$/\1/ |
||
− | |||
− | the % says to do the substitution on every line in the document |
||
− | pattern is the pattern we're searching for |
||
− | the \( and \) stores our pattern in a variable (in our case, variable \1) |
||
− | the .* matches any amount of characters |
||
− | the $ matches the end of the line |
||
− | the \1 is a variable storing pattern |
||
− | so the whole thing replaces pattern and everything following it until the end of the line by the pattern alone |
||
− | |||
− | to memyselfandi: |
||
− | |||
− | your first question: |
||
− | |||
− | :%s/^.*\(pattern\)/\1/ |
||
− | |||
− | the % says to do the substitution on every line in the document |
||
− | the ^ says to match the beginning of a line |
||
− | the .* says to match any amount of characters |
||
− | the \( and \) stores our pattern in a variable (in our case, variable \1) |
||
− | "pattern" is whatever pattern you want to search for |
||
− | \1 is a variable holding the contents of the pattern |
||
− | so basically, the whole thing replaces everything from the beginning of the line to the pattern by the pattern alone |
||
− | |||
− | your second question: |
||
− | |||
− | :1,7s/^.\{5\}// |
||
− | |||
− | the 1,7 wold do the replacement on lines 1 through 7. Replace 1 and 7 by whatever you want |
||
− | the ^ says to match the beginning of the line |
||
− | the . says to match any character |
||
− | the \{5\} says to match the preceding character 5 times. Replace 5 by whatever you want |
||
− | so basically, the whole thing deletes the first 5 characters from lines 1 through 7 |
||
− | |||
− | Anonymous |
||
− | , September 4, 2006 13:55 |
||
− | ---- |
||
− | Compress multiple occurences of blank lines into a single blank line |
||
− | |||
− | :v/./,/./-j |
||
− | |||
− | cd to the "docs" directory of vim, |
||
− | |||
− | grep '\/,\/' *.txt |
||
− | |||
− | to find occurences of /,/ that can be investigated further to find |
||
− | an explanation of what vim is doing. |
||
− | |||
− | daN.thompOsonS--AT--yaPhAooM |
||
− | , September 16, 2006 18:11 |
||
− | ---- |
||
− | :v/./,/./-j |
||
− | |||
− | I'll break down this incredible collapse-multiple-blank-lines command for everyone, now that I finally figured out how it works. |
||
− | |||
− | First, however, I'll rewrite it this way to illustrate that some of those slashes have totally different meaning than others: |
||
− | |||
− | :v_._,/./-1join |
||
− | |||
− | Note that to delimit expressions like these, just about any symbol can be used in place of the typical slashes... in this case, I used underscores. What we have is an inverse search (:v, same as :g!) for a dot ('.') which means anything except a newline. So this will match empty lines and proceed to execute [command] on each of them. |
||
− | |||
− | :v_._[command] |
||
− | |||
− | The remaining [command] is this, which is a fancy join command, abbreviated earlier as just 'j'. |
||
− | |||
− | ,/./-1join |
||
− | |||
− | The comma tells it to work with a range of lines: |
||
− | |||
− | :help :, |
||
− | |||
− | With nothing before the comma, the range begins at the cursor, which is where that first blank line was. The end of the range is specified by a search, which to my knowledge actually does require slashes. The slash and dot mean to search for anything (again), which matches the nearest non-empty line and offsets by {offset} lines. |
||
− | |||
− | /./{offset} |
||
− | |||
− | The {offset} here is -1, meaning one line above. In the original command we just saw a minus sign, to which vim assumes a count of 1 by default, so it did the same thing as how I've rewritten it, but simply with one character fewer to type. |
||
− | |||
− | /./-1 |
||
− | |||
− | There is a caveat about join that makes this trick possible. If you specify a range of only one line to "join", it will do nothing. For example, this command tells vim to join into one line all lines from 5 to 5, which does nothing: |
||
− | |||
− | :5,5join |
||
− | |||
− | In this case, any time you have more than one empty line (the case of interest), the join will see a range greater than one and join them together. For all single empty lines, join will leave it alone. |
||
− | |||
− | There's no good way use a delete command with :v/./ because you have to delete one line for every empty line you find. Join turned out to be the answer. |
||
− | |||
− | This command only merges truly "empty" lines... if any lines contain spaces and/or tabs, they will not be collapsed. To make sure you kill those lines, try this: |
||
− | |||
− | :v/^[^ \t]\+$/,/^[^ \t]\+$/-j |
||
− | |||
− | Or, to just clean such lines up first, |
||
− | |||
:%s/^[ \t]\+$//g |
:%s/^[ \t]\+$//g |
||
+ | </pre> |
||
− | '''Anonymous''' |
||
− | , October 17, 2006 18:18 |
||
---- |
---- |
||
+ | Here is a 'g' version that does the same thing as that last 'v' command |
||
− | "Is there way I can use :g to search a pattern and delete from that pattern to the end of line instead of deleting the whole line." |
||
+ | <pre> |
||
− | |||
+ | :g/^[ <TAB>]*$/,/[^ <TAB>]/-j |
||
− | Not that I have found! |
||
+ | </pre> |
||
− | |||
− | I use the ${var%string} from bash/ksh instead |
||
− | |||
− | |||
− | ask2--AT--runbox.com |
||
− | , October 30, 2006 23:37 |
||
− | ---- |
||
− | I have a malformed XML file with a structure like this: |
||
− | |||
− | <authors> |
||
− | <author> |
||
− | Blogs, Joe |
||
− | </author> |
||
− | <author> |
||
− | Smith, Fred |
||
− | </author> |
||
− | <author> |
||
− | Jones, David |
||
− | </author> |
||
− | </authors> |
||
− | |||
− | How do I use :g and the join command to get rid of those new lines, so the structure ends up like this: |
||
− | |||
− | <authors> |
||
− | <author>Blogs, Joe</author> |
||
− | <author>Smith, Fred</author> |
||
− | <author>Jones, David</author> |
||
− | </authors> |
||
− | |||
− | What I need to do is search for '<author>' and then join the next line (-1j, right?), and then the next one (containing </author>) to the previous one. |
||
− | These XML files are large (>1000 lines) so a global find and replace would be great. Thanks in advance! |
||
− | |||
− | tatlar--AT--yahoo.com |
||
− | , November 1, 2006 9:50 |
||
− | ---- |
||
− | Figured out my malformed XML issue in the note above, in a 2 step process: |
||
− | |||
− | 1) Find and replace '<author>\n' (where \n is a newline) with '<author>': |
||
− | |||
− | :%s/<author>\n/<author>/g |
||
+ | However, all the above blank line merging method fails to merge multiple blank lines at the end of a file. The solution is to add then remove an extra line at the end of the file. As such this is the complete blank line compressor command... |
||
− | 2) Use :g to find '</author>' and do a negative join (join with previous line): |
||
+ | <pre> |
||
+ | :$s/$/\\rZ/ |
||
+ | :g/^[ <TAB>]*$/,/[^ <TAB>]/-j |
||
+ | :$d |
||
+ | </pre> |
||
+ | Or in the form of an easy to use macro, which also tries to return to to your original place in the file. |
||
− | :g/<\/author>/-1j |
||
+ | <pre> |
||
+ | :map QE mz:$s/$/\\rZ/<CR>:g/^[ <TAB>]*$/,/[^ <TAB>]/-j<CR>Gdd`z |
||
+ | </pre> |
||
− | tatlar--AT--yahoo.com |
||
− | , November 1, 2006 10:17 |
||
---- |
---- |
||
+ | As always, There's More Than One Way To Do It: |
||
− | I am searching for a regexp on a line with thousands of line, while doing :g/<regexp>/p it prints the whole line, I want it to only print the regexp i.e. \1 variable so that I can copy all those lines manually in a file, and is there any way inside vim only to re-direct the regexp results found into a file. |
||
+ | <pre> |
||
+ | :%s/^$\n^$//g |
||
+ | </pre> |
||
+ | This uses a substution (s/foo/bar/) that matches two consecutive blank lines and turns them into one. Applied globally (%), and multiple times to the same line (g), this works exactly as you'd want it to. |
||
− | mail_the_cv--AT--yahoo.com |
||
− | , January 28, 2007 23:46 |
||
---- |
---- |
||
+ | Another way to collapse empty lines, including whitespace, is: |
||
− | <!-- parsed by vimtips.py in 0.627565 seconds--> |
||
+ | <pre> |
||
+ | :%s/^\_s\+/\r/g |
||
+ | </pre> |
||
+ | <code>\_s</code> matches whitespace (space and tab) ''including'' end of line, <code>\+</code> matches 1 or more of those, as many as possible, <code>\r</code> inserts carriage return specific to file format (unix-dos-mac). |
Revision as of 10:34, 27 January 2014
created 2002 · complexity intermediate · author Arun Easi · version 6.0
The global command :g
is very useful. Here are some examples showing the power of :g
.
Brief explanation of :g
:[range]g/<pattern>/cmd
This will act on the specified [range] (default whole file), by executing the Ex command cmd (An Ex command is one starting with a colon (':')) for each line matching <pattern>. Before executing cmd, "." is set to the current line.
Examples
Display context (5 lines) for all occurrences of a pattern.
:g/<pattern>/z#.5 " Same, but with some beautification. :g/<pattern>/z#.5|echo "=========="
Delete all lines matching a pattern.
:g/<pattern>/d
Delete all lines that do not match a pattern.
:g!/<pattern>/d
Delete all blank lines (^
is start of line; \s*
is zero or more whitespace characters; $
is end of line)
:g/^\s*$/d
Double space the file (^
is start of line which matches each line).
:g/^/pu =\"\n\" " Alternative (:put inserts nothing from the blackhole register) :g/^/pu _
Copy all lines matching a pattern to end of file.
:g/<pattern>/t$
Move all lines matching a pattern to end of file.
:g/<pattern>/m$
Copy all lines matching a pattern to register 'a'.
qaq:g/<pattern>/y A
- Explanation
qaq
is a trick to clear registera
(qa
starts recording a macro to registera
, thenq
stops recording, leavinga
empty).y A
is an Ex command (:help :y). It yanks the current line into registerA
(append to registera
).
Increment each number at the start of a line, from the current line to end-of-file, by one (the exclamation mark in :normal!
means this will work even if Ctrl-A has been mapped to perform a function other than its default of incrementing a number).
:.,$g/^\d/exe "normal! \<C-A>"
Comment lines containing "DEBUG" statements in a C program.
" using :normal g/^\s*DEBUG/exe "norm! I/* \<Esc>A */\<Esc>" " using :substituting g/^\s*DEBUG/s!.*!/* & */!
Reverse lookup for records (say an address book, with Name at start-of-line and fields after a space).
:g/<pattern>/?^\w?p "if only name is interesting :g/<pattern>/ka|?^\w?p|'ap "if name and the lookup-line is interesting :g/<pattern>/?^\w?|+,/^[^ ]/-1p "if entire record is interesting
- Explanation See :help :range for the meaning of the constructs in the
[cmd]
portion of the:g
commands.
Reverse a file (just to show the power of g).
:g/^/m0
- Explanation According to :help multi-repeat,
:g
and its cousin:v
work in a two-pass manner. The first pass of:g
marks every line matching{pattern}
, while the second pass (apparently performed starting at the file's beginning and proceeding to the end) performs the[cmd]
. The above use of:g
takes advantage of the order the lines are processed in (which is probably okay, though probably not technically guaranteed). It works by first marking every line, then moving the first marked line to the top of the file, then moving the second to the top of the file (above the line moved previously), then the third marked line (again above the previously moved line), and so on until the last line in the file is moved to the top, effectively reversing the file. Note that if:g
processed lines in any order other than from top to bottom, this command would not work.
Add text to the end of a line that begins with a certain string.
:g/^pattern/s/$/mytext
Notes
Use :v
to reVerse the sense of the search pattern. Example: Delete all lines not matching pattern:
:v/pattern/d
Some explanation of commands commonly used with :g
:2,8co15 "copy lines 2 through 8 after line 15 :4,15t$ "copy lines 4 through 15 to end of document (t == co) :-t$ "copy previous line to end of document :m0 "move current line to line 0 (i.e. the top of the document) :.,+3m$-1 "current line through current+3 are moved to the lastLine-1 (i.e. next to last)
Since commands used with :g are Ex commands, searching for help should include the colon.
:help :<help-topic> :help :k "example
References
- :help ex-cmd-index provides a list of Ex commands.
- :help 10.4 is the section of the user manual discussing the :global command.
- :help multi-repeat talks about both the :g and :v commands.
Comments
Over a range defined by marks a and b, operate on each line containing pattern. The operation is to replace each pattern2 with string.
:'a,'bg/pattern/s/pattern2/string/gi
Run a macro on matching lines (example assuming a macro recorded as 'q'):
:g/<pattern>/normal @q
To delete (subsequent) duplicate lines from a file:
:g/^\(.*\)\(\r\?\n\1\)\+$/d :%!uniq
To just view the duplicates use:
/^\(.*\)\(\r\?\n\1\)\+$
Compress multiple occurrences of blank lines into a single blank line
:v/./,/./-j
Use :helpgrep '\/,\/' *.txt
for an explanation.
I'll break down this incredible collapse-multiple-blank-lines command for everyone, now that I finally figured out how it works.
First, however, I'll rewrite it this way to illustrate that some of those slashes have totally different meaning than others:
:v_._,/./-1join
Note that to delimit expressions like these, just about any symbol can be used in place of the typical slashes... in this case, I used underscores. What we have is an inverse search (:v, same as :g!) for a dot ('.') which means anything except a newline. So this will match empty lines and proceed to execute [command] on each of them.
:v_._[command]
The remaining [command] is this, which is a fancy join command, abbreviated earlier as just 'j'.
,/./-1join
The comma tells it to work with a range of lines:
:help :,
With nothing before the comma, the range begins at the cursor, which is where that first blank line was. The end of the range is specified by a search, which to my knowledge actually does require slashes. The slash and dot mean to search for anything (again), which matches the nearest non-empty line and offsets by {offset} lines.
/./{offset}
The {offset} here is -1, meaning one line above. In the original command we just saw a minus sign, to which vim assumes a count of 1 by default, so it did the same thing as how I've rewritten it, but simply with one character fewer to type.
/./-1
There is a caveat about join that makes this trick possible. If you specify a range of only one line to "join", it will do nothing. For example, this command tells vim to join into one line all lines from 5 to 5, which does nothing:
:5,5join
In this case, any time you have more than one empty line (the case of interest), the join will see a range greater than one and join them together. For all single empty lines, join will leave it alone.
There's no good way use a delete command with :v/./ because you have to delete one line for every empty line you find. Join turned out to be the answer.
This command only merges truly "empty" lines... if any lines contain spaces and/or tabs, they will not be collapsed. To make sure you kill those lines, try this:
:v/^[^ \t]\+$/,/^[^ \t]\+$/-j
Or, to just clean such lines up first,
:%s/^[ \t]\+$//g
Here is a 'g' version that does the same thing as that last 'v' command
:g/^[ <TAB>]*$/,/[^ <TAB>]/-j
However, all the above blank line merging method fails to merge multiple blank lines at the end of a file. The solution is to add then remove an extra line at the end of the file. As such this is the complete blank line compressor command...
:$s/$/\\rZ/ :g/^[ <TAB>]*$/,/[^ <TAB>]/-j :$d
Or in the form of an easy to use macro, which also tries to return to to your original place in the file.
:map QE mz:$s/$/\\rZ/<CR>:g/^[ <TAB>]*$/,/[^ <TAB>]/-j<CR>Gdd`z
As always, There's More Than One Way To Do It:
:%s/^$\n^$//g
This uses a substution (s/foo/bar/) that matches two consecutive blank lines and turns them into one. Applied globally (%), and multiple times to the same line (g), this works exactly as you'd want it to.
Another way to collapse empty lines, including whitespace, is:
:%s/^\_s\+/\r/g
\_s
matches whitespace (space and tab) including end of line, \+
matches 1 or more of those, as many as possible, \r
inserts carriage return specific to file format (unix-dos-mac).