Vim Tips Wiki
Edit Page
We recommend that you log in before editing. This will allow other users to leave you a message about your edit, and will let you track edits via your Watchlist. Creating an account is quick and free.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
  +
== Overview ==
{{TipNew
 
  +
''Ranges'' permit a command to be applied over a subset of a file's lines. By default, the range of a Vim command is the current line. It can be helpful to think in terms of commands being executed over a one-line range of lines, and of range changes as modifiers to the range.
|id=1611
 
|previous=1610
 
|next=1612
 
|created=2008
 
|complexity=basic
 
|author=
 
|version=7.0
 
|subpage=/200812
 
|category1=Usage
 
|category2=
 
}}
 
A ''range'' permits a command to be applied to a group of lines in the current buffer. For most commands, the default range is the current line. For example:
 
*<code>:s/old/new/g</code> &nbsp;&nbsp;changes all ''old'' to ''new'' in the current line
 
*<code>:11,15s/old/new/g</code> &nbsp;&nbsp;changes lines 11 to 15 inclusive
 
*<code>:%s/old/new/g</code> &nbsp;&nbsp;changes all lines
 
   
  +
In general, range modifications should be specified in the form <code>'''x,y'''</code> where '''x''' is the number of a line in a file and '''y''' is a ''subsequent line'' in the same file; though there are some special options as well:
==Examples==
 
A range can be specified using line numbers or special characters, as in these examples:
+
* The percent sign (%) is used as a special sigil to denote all lines in the file.
  +
* The special syntax '''.,.x''' can be used to denote '''x''' lines from the current line.
{| class="wikitable"
 
!Range !! Description !! Example
 
|-
 
| <code>21</code> || line 21 || <code>:21s/old/new/g</code>
 
|-
 
| <code>1</code> || first line || <code>:1s/old/new/g</code>
 
|-
 
| <code>$</code> || last line || <code>:$s/old/new/g</code>
 
|-
 
| <code>.</code> || current line || <code>:.w single.txt</code>
 
|-
 
| <code>%</code> || all lines (same as <code>1,$</code>) || <code>:%s/old/new/g</code>
 
|-
 
| <code>21,25</code> || lines 21 to 25 inclusive || <code>:21,25s/old/new/g</code>
 
|-
 
| <code>21,$</code> || lines 21 to end || <code>:21,$s/old/new/g</code>
 
|-
 
| <code>.,$</code> || current line to end || <code>:.,$s/old/new/g</code>
 
|-
 
| <code>.+1,$</code> || line ''after'' current line to end || <code>:.+1,$s/old/new/g</code>
 
|-
 
| <code>.,.+5</code> || six lines (current to current+5 inclusive) || <code>:.,.+5s/old/new/g</code>
 
|-
 
| <code>.,.5</code> || same (<code>.5</code> is interpreted as <code>.+5</code>) || <code>:.,.5s/old/new/g</code>
 
|}
 
   
The <code>:s///</code> command substitutes in the specified lines. The <code>:w</code> command writes a file. On its own, <code>:w</code> writes all lines from the current buffer to the file name for the buffer. Given a range and a file name, <code>:w</code> writes only the specified lines to the specified file. The example above creates file <code>single.txt</code> containing the current line.
 
   
  +
;Mnemonic: The '''o/o''' of a percent sign resembles the '''x,y''' and '''.,.''' structure of ranges, but with a "wildcard" for each number.
If you know you want to substitute in six lines, starting from the current line, you can use either of the ranges shown above. An easier method is to enter a count value (type <code>6</code>), then enter the colon command with no range (type <code>:s/old/new/g</code>). Because you entered a count, Vim displays the command:
 
<pre>
 
:.,.+5s/old/new/g
 
</pre>
 
   
==Default range==
 
For most commands, the default range is <code>.</code> (the current line, for example, <code>:s///</code> substitutes in the current line). However, for <code>:g//</code> and <code>:w</code> the default is <code>%</code> (all lines).
 
   
  +
Ranges should always be ''forward'' ranges -- that is, it should always be true that '''x''' < '''y'''. Inverting the range by making '''y''' < '''x''' (such as, <pre style="display: inline; padding: 1px 3px;">:14,10s/abc/def/g</pre>) will cause Vim to object, prompting the user as to whether the '''x''' and '''y''' should be reversed:
{| class="wikitable"
 
  +
Backwards range given, OK to swap (y/n)?
!Example !! Equivalent !! Description
 
  +
Choosing "y" here will cause Vim to invert the range (making it a ''forward'' range) and execute the command. Choosing "n" will abort the operation.
|-
 
| <code>:s/old/new/g</code> || <code>:.s/old/new/g</code> || substitute in current line
 
|-
 
| <code>:g/old/</code> || <code>:%g/old/</code> || list all lines matching <code>old</code>
 
|-
 
| <code>:w my.txt</code> || <code>:%w my.txt</code> || write all lines to file <code>my.txt</code>
 
|}
 
   
==Selections==
+
== Range Errors ==
  +
When a user requests that a command be applied over a range of lines beyond those found in the file, Vim will object with an error:
A command like <code>:123,145s/old/new/g</code> substitutes in lines 123 to 145 inclusive, but what if you're not sure what the line numbers are? One method is to use ''marks'': Type <code>ma</code> in the first line, then type <code>mb</code> in the last line (to set marks <code>a</code> and <code>b</code>). Then enter command <code>:'a,'bs/old/new/g</code> to substitute in lines from mark <code>a</code> to <code>b</code>, inclusive.
 
  +
E16: Invalid range
   
  +
== Examples ==
Another method is to visually select lines, then enter a colon command (for example, <code>:s/old/new/g</code>). Note that you do not enter a range. However, because the command was entered while lines were selected, Vim displays the command as:
 
<pre>
 
:'<,'>s/old/new/g
 
</pre>
 
   
  +
=== Current line ===
The range <code>'<,'></code> is entered automatically to identify the lines that were last visually selected (they do not need to be visually selected now).
 
  +
By default, the range of a Vim command is the current line. The following command will replace the letters "abc" with "def" on the current line:
  +
:s/abc/def/
   
  +
;''Note'': Use the "g" flag at the end of the replacement to replace globally (within the range). That is, the above command will convert <code>abc,abc</code> to <code>def,abc</code>. To replace ''every'' occurrence of "abc" with "def", use the command <pre style="display: inline; padding: 1px 3px;">:s/abc/def/g</pre>. See [[Search and replace]] for more information.
For example, you might type <code>vip</code> to visually select "inner paragraph" (the paragraph holding the cursor). Then type <code>:s/old/new/g</code> to substitute in all lines in the selected paragraph.
 
   
  +
=== Between specific line numbers ===
==Deleting, copying and moving==
 
  +
Using the above string replacement example, we can modify the range to replace all occurrences of "abc" with "def" between any two lines in the file (inclusive) using the '''x,y''' syntax for range modification. Specific ranges should always be ''forward'' ranges (see [[Ranges#Overview|the Overview section]] above for details). For example, to execute the replacement over lines 10, 11, 12, and 13, we may type
Ranges work with Ex commands (those typed after a colon, for example, <code>:w</code>). As well as the commands we've seen so far, it's handy to know how to use <code>:d</code> (delete lines), <code>:t</code> or <code>:co</code> (copy lines), and <code>:m</code> (move lines).
 
  +
:10,13s/abc/def/g
   
  +
=== X lines from the current line ===
{| class="wikitable"
 
  +
Use the special '''.,.x''' syntax to modify the range to apply to the current line and '''x''' subsequent lines. Thus, to replace all occurrences of "abc" with "def" in the current line and the next 4 lines, we may type
!Command !! Description
 
  +
:.,.4s/abc/def/g
|-
 
| <code>:21,25d</code> || delete lines 21 to 25 inclusive
 
|-
 
| <code>:$d</code> || delete the last line
 
|-
 
| <code>:1,.-1d</code> || delete all lines before the current line
 
|-
 
| <code>:.+1,$d</code> || delete all lines after the current line
 
|-
 
| <code>:21,25t 30</code> || copy lines 21 to 25 inclusive to just after line 30
 
|-
 
| <code>:$t 0</code> || copy the last line to before the first line
 
|-
 
| <code>:21,25m 30</code> || move lines 21 to 25 inclusive to just after line 30
 
|-
 
| <code>:$m 0</code> || move the last line to before the first line
 
|}
 
   
  +
If the current line is line 100, then all occurrences of "abc" will be replaced with "def" in lines 100, 101, 102, 103, and 104.
The line numbers in a command are those ''before'' the command executes. In the earlier example which moved lines 21..25 to after 30, the "30" refers to the line number before the move occurred.
 
   
  +
Because of this, it is permissible to restrict a command to the current line explicitly with the following syntax:
==Ranges with marks and searches==
 
  +
:.,.0s/abc/def/g
In a range, a line number can be given as:
 
  +
which will be interpreted that the command should be executed over the current line ''and zero subsequent lines''. It's usually better simply to use the implicit "current-line" range interpretation provided by
*A mark (for example, <code>'x</code> is the line containing mark <code>x</code>).
 
  +
:s/abc/def/g
*A search (for example, <code>/pattern/</code> is the next line matching ''pattern'').
 
   
  +
It is also permissible to restrict a command to the current line semi-explicitly by omitting the '''x''' entirely:
When using a mark, it must exist in the current buffer.
 
  +
:.,.s/abc/def/g
   
  +
Finally, for advanced users, it should be noted that Vim's interpretation of the '''.,.x''' range modifier is ''symbolic'' and not ''iterative''; that is, rather than iterating the command over '''x''' lines, the current line number is first calculated, then the last line number, and (effectively) a standard range modifier is applied. So if the cursor is currently on line 30 and the command
{| class="wikitable"
 
  +
:.,.12s/abc/def/g
!Command !! Description
 
  +
is executed, the lines involved will be internally calculated and applied as
|-
 
  +
:30,42s/abc/def/g
| <code>:'a,'bd</code> || delete lines from mark <code>a</code> to mark <code>b</code>, inclusive
 
|-
 
| <code>:.,'bd</code> || delete lines from the current line to mark <code>b</code>, inclusive
 
|-
 
| <code>:'a,'bm 0</code> || move lines from mark <code>a</code> to <code>b</code> inclusive, to the beginning
 
|-
 
| <code>:'a,'bw file.txt</code> || write lines from mark <code>a</code> to <code>b</code> to file.txt
 
|-
 
| <code>:'a,'bw >> file.txt</code> || append lines from mark <code>a</code> to <code>b</code> to file.txt
 
|}
 
   
  +
It is possible to exploit this mechanism to apply an ''backwards'' range from the current line by using a negative value for '''x'''. Thus, if the current cursor is on line 30 and the command
Here are some examples using searches:
 
  +
:.,.-12s/abc/def/g
;<code>:.,/green/co $</code>
 
  +
is executed, it will be interpreted as the command
:Copy the lines from the current line to the next line containing 'green' (inclusive), to the end of the buffer.
 
  +
:30,18s/abc/def/g
;<code>:/apples/,/apples/+1s/old/new/g</code>
 
:Replace all "old" in the next line in which the "apples" occurs, and the line following it.
 
;<code>:/apples/;.1s/old/new/g</code>
 
:Same (<code>.1</code> is <code>.+1</code>, and because <code>;</code> was used, the cursor position is set to the line matching "apples" ''before'' interpreting the <code>.+1</code>).
 
;<code>:/apples/,.100s/old/new/g</code>
 
:Replace all "old" in the next line in which "apples" occurs, and all lines up to and including 100 lines after the current line (where the command was entered).
 
   
  +
As this is a ''backwards'' range, Vim will object, asking the user
To do a replace in blocks identified by an initial and a final pattern:
 
  +
Backwards range given, OK to swap (y/n)?
;<code>:/apples/,/peaches/ s/old/new/g</code>
 
:Replace all "old" in the first block that starts with "apples" and ends with "peaches".
 
:<code>/apples/</code> identifies the first line after the cursor containing "apples".
 
:<code>/peaches/</code> is similar (first line after the current line, ''not'' the first after "apples"). Be aware of backwards ranges.
 
:The block is all lines from "apples" to "peaches", inclusive.
 
;<code>:/apples/;/peaches/ s/old/new/g</code>
 
:Same, but "peaches" identifies the first occurrence ''after'' "apples".
 
;<code>:/apples/,/peaches/ s/^/# /g</code>
 
:Insert "<code># </code>" at the start of each line in the first block.
 
;<code>:/apples/+1,/peaches/-1 s/^/# /g</code>
 
:Insert "<code># </code>" at the start of each line inside the block.
 
   
  +
Choosing "y" will cause Vim to reverse the range to
To do a global replace in all blocks with the same patterns, [[Power of g|use <code>:g</code>]]:
 
  +
:18,30s/abc/def/g
;<code>:g/apples/,/peaches/ s/^/# /g</code>
 
  +
giving the desired effect.
:Insert "<code># </code>" at the start of each line in all identified blocks.
 
:<code>:g/apples/</code> identifies each line containing "apples".
 
:In each such line, <code>.,/peaches/ s/^/# /g</code> is executed
 
:(the <code>.</code> is assumed; it means the current line, where "apples" occurs).
 
;<code>:g/^function!\? \(s:\)\?My/;/^endfunction/s/^/" /</code>
 
:''This example is for a Vim script where functions start with <code>function</code> or <code>function!</code> and end with <code>endfunction</code>.''
 
:Insert "<code>" </code>" at the start of each line in each block.
 
:All functions that start with <code>function My</code> or <code>function s:My</code> will be commented out.
 
:The last line in each block is where <code>endfunction</code> first occurs (at the left margin), after where <code>function My</code> is found.
 
   
  +
The added inconvenience of the extra "y" keystroke may be mitigated for some users by the ability to execute a ''backwards-range'' command from the current cursor location.
Even more tricks are available; see {{help|cmdline-ranges}}. Summary:
 
   
  +
It should be noted that this is probably not an expected or desired behavior and may be changed in subsequent versions of Vim. Habituate yourself at your own risk =)
{| class="wikitable"
 
  +
!Item !! Description
 
  +
=== All lines ===
|-
 
  +
As mentioned in the overview above, there is a special sigil to modify the range to apply to all lines in the current file: the percent sign ('''%'''). It can be used this way:
| <code>/pattern/</code> || next line where ''pattern'' matches
 
  +
:%s/abc/def/g
|-
 
  +
| <code>?pattern?</code> || previous line where ''pattern'' matches
 
  +
=== Cheat sheet ===
|-
 
  +
The following "range cheat sheet" can be used as a quick-reference, and can be included dynamically in other articles in the Vim wiki.
| <code>\/</code> || next line where the previously used search pattern matches
 
  +
<onlyinclude><table style="border: 1px solid #aaaaaa;" cellpadding=0 cellspacing=0>
|-
 
  +
<caption style="background-color: #aaaaaa; color: white">Range cheat sheet (from [[Ranges]])</caption>
| <code>\?</code> || previous line where the previously used search pattern matches
 
  +
<tr style="background-color: #fec423;">
|-
 
  +
<th>Command</th>
| <code>\&</code> || next line where the previously used substitute pattern matches
 
  +
<th style="text-align: left; padding: 2px 5px;">Description</th>
|-
 
  +
</tr>
| <code>0;/that</code> || first line containing "that" (also matches in the first line)
 
  +
<tr>
|-
 
  +
<td><code style="padding: 2px 5px; margin: 2px;">:s/abc/def/g</code></td>
| <code>1;/that</code> || first line after line 1 containing "that"
 
  +
<td style="padding: 2px 5px;">Replace "abc" with "def" in the current line</td>
|}
 
  +
</tr>
  +
<tr>
  +
<td><code style="padding: 2px 5px; margin: 2px;">:.,.12s/abc/def/g</code></td>
  +
<td style="padding: 2px 5px;"> Replace "abc" with "def" in the current line and the 12 following lines </td>
  +
</tr>
  +
<tr>
  +
<td><code style="padding: 2px 5px; margin: 2px;">:10,35s/abc/def/g</code></td>
  +
<td style="padding: 2px 5px;">Replace "abc" with "def" between lines 10 and 35</td>
  +
</tr>
  +
<tr>
  +
<td><code style="padding: 2px 5px; margin: 2px;">:%s/abc/def/g</code></td>
  +
<td style="padding: 2px 5px;">Replace "abc" with "def" in all lines</td>
  +
</tr>
  +
</table></onlyinclude>
  +
  +
  +
''Use the wiki markup'' <code><nowiki>{{:Ranges}}</nowiki></code> ''to include this cheat sheet into other articles. See [[Help:Transclusion]] for more information this process.''
   
 
==Comments==
 
==Comments==
I find this counter-intuitive to define a range with commas. Examples : 21,25
 
   
  +
Also should mention other things in {{help|:range}}
I would prefer 21-25 ... --July 19, 2016
 
----
 
A dash cannot be used because it refers to negative numbers, relative to the current line. The following uses range <code>-3,-1</code> to yank (copy) the three line just before each line containing "password".
 
 
<pre>
 
<pre>
  +
$ = last line in file
:let @a=''
 
  +
't = position of mark t
:g/password/-3,-1y A
 
  +
'T = position of mark T if it is in the same buffer
:new
 
  +
/{pattern}/ = next line where pattern matches
:put a
 
  +
?{pattern}? = previous line where pattern matches
  +
\/ = next place previous search pattern matches
  +
\? = previous place previous search pattern matches
  +
\& = next place previous substitution pattern matches
 
</pre>
 
</pre>
[[User:JohnBeckett|JohnBeckett]] ([[User talk:JohnBeckett|talk]]) 00:05, July 30, 2016 (UTC)
 
----
 
Is there more documentation on the concept of "count value", as in this sentence from the wiki above:
 
   
  +
I find <tt>/{pattern}/</tt> to be especially useful.
"An easier method is to enter a count value (type 6), then enter the colon command with no range" ... ? --August 22, 2016
 
  +
:See {{help|N:}} for "Count and Range". It has the example of <code>3:d<CR></code> being translated to <code>.,.+2d<CR></code>. [[User:JohnBeckett|JohnBeckett]] ([[User talk:JohnBeckett|talk]]) 06:04, August 23, 2016 (UTC)
 
  +
Also mention that +{number} and -{number} can be added to the end of any of the range values to adjust the line number.
----
 
  +
  +
For example:
  +
  +
<tt><nowiki>:/apples/,/apples/+1s/oranges/bananas/g</nowiki></tt> will replace all occurrences of "oranges" in the next line in which the word "apples" occurs and the line following it.
Please note that all contributions to the Vim Tips Wiki are considered to be released under the CC-BY-SA
Cancel Editing help (opens in new window)