Vim Tips Wiki
No edit summary
(highlighted "keep only unique lines" - it was easy to assume the 'u' was part of what 'sort' needed to operate)
Tag: Visual edit
(41 intermediate revisions by 19 users not shown)
Line 1: Line 1:
  +
{{TipImported
{{review}}
 
{{Tip
 
 
|id=1166
 
|id=1166
  +
|previous=1164
|title=Sort lines - easy use of existing vim capability
 
  +
|next=1167
|created=March 9, 2006 7:25
+
|created=2006
 
|complexity=basic
 
|complexity=basic
|author=Robert Stovall in Dallas
+
|author=Robert Stovall
|version=5.7
+
|version=7.0
 
|rating=29/17
 
|rating=29/17
  +
|category1=
|text=
 
  +
|category2=
This is just a reminder of how to take advantage of existing VIM capability. I had not needed to sort before and took a few minutes to find a good example.
 
 
}}
  +
Vim has a very powerful built-in sort utility, or it can interface with an external one. In order to '''''keep only unique lines''''' in Vim, you would:
   
  +
<pre>
 
:{range}sort u
  +
</pre>
   
 
Yes, it's that simple.
   
  +
You could create a range in advance, such as <code>'a,.</code> (from mark 'a' to the current line) or you could create one on-the-fly using visual selection by pressing ':' in visual mode, after selecting the text you wish to sort, to get a range of <code>'<,'></code> on the command line.
Sort lines in vim using blocks:
 
   
  +
If you like using an external sort utility instead, you can do it just as easily. For example, Unix sort, removing duplicate lines:
   
  +
<pre>
 
:{range}!sort -u
  +
</pre>
   
  +
Many other systems also have an external sort utility, but the options and capabilities will differ. It is probably better to use the built-in Vim sort unless you are looking for a specific feature of the external sort (or using an old Vim without the <code>:sort</code> command).
:&lt;range&gt;!sort
 
   
  +
==Examples==
  +
===Sort in reverse===
  +
<pre>:%sort!</pre>
   
  +
===Sort, removing duplicate lines===
  +
<pre>:%sort u</pre>
   
  +
===Sort using the external Unix sort utility, respecting month-name order===
Yes, its that simple.
 
  +
<pre>:%!sort -M</pre>
  +
("respecting month-name order" means January < February < ... < December)
   
  +
===Numeric sort===
  +
<pre>:sort n</pre>
  +
(this way, 100 doesn't precede 20 in the sort)
   
  +
===Sort subsections independently, in this example sort numbers between "start" and "end" markers===
  +
<pre>:g/start/+1,/end/-1 sort n</pre>
   
  +
=== Sort only specific lines using ranges ===
Key strokes:
 
  +
sort lines 296 to 349, inclusive
  +
:296,349sort
   
  +
=== Sort by pattern ===
  +
When working with Javascript ES6, it may be useful to sort your imports
   
  +
<pre>
  +
import './ProjectTemplateEditModal.scss';
  +
import * as _ from "lodash";
  +
import Moment from 'moment';
  +
import React from 'react';
  +
import { Button, Col, Modal, Row, Label } from 'react-bootstrap';
  +
import { CurrencyControl } from '../../Core/Components/Controls';
  +
import { DynamicModalMixin } from '../../Core/Components/Modals';
  +
import { ProjectTemplateStore } from '../Stores/ProjectTemplateStore';
  +
import { StoreBinder } from '../../Core/Utils/StoreBinder';
  +
import { TextAreaControl } from '../../Core/Components/Controls/TextAreaControl';
  +
import { TextBoxControl } from '../../Core/Components/Controls/TextBoxControl';
  +
import { TooltipWrapper } from '../../Core/Components/Tooltips/TooltipWrapper';
  +
import { withRouter } from 'react-router';
  +
</pre>
  +
  +
It is possible to pass a regex expression to sort. Any lines that do not match the expression will be sorted normally, while lines that do match will be sorted on the text that *follows* the expression. <pre>:{range}sort /\/[A-z]/</pre> This will organize your imports relative to the "package" they are related to:
   
  +
<pre>
1) Place cursor at first line of range to be sorted.
 
  +
import * as _ from "lodash";
  +
import Moment from 'moment';
  +
import React from 'react';
  +
import { Button, Col, Modal, Row, Label } from 'react-bootstrap';
  +
import { withRouter } from 'react-router';
  +
import { CurrencyControl } from '../../Core/Components/Controls';
  +
import { TextAreaControl } from '../../Core/Components/Controls/TextAreaControl';
  +
import { TextBoxControl } from '../../Core/Components/Controls/TextBoxControl';
  +
import { DynamicModalMixin } from '../../Core/Components/Modals';
  +
import { TooltipWrapper } from '../../Core/Components/Tooltips/TooltipWrapper';
  +
import { StoreBinder } from '../../Core/Utils/StoreBinder';
  +
import './ProjectTemplateEditModal.scss';
  +
import { ProjectTemplateStore } from '../Stores/ProjectTemplateStore';
  +
</pre>
  +
  +
You can also sort on text that *matches* the regex by including the 'r' flag, for example: <pre>:{range}sort /\/[A-z]/ r</pre>
   
  +
==See also==
2) Use marker (ma) to mark starting point
 
  +
*[[VimTip374|374 Use filter commands to process text]]
  +
*[[VimTip588|588 How to sort using visual blocks]]
  +
*[[VimTip758|758 Search and sort by selection]]
  +
*[[VimTip800|800 Sorting lines in a file based on the number of words in each line]]
  +
*[[VimTip923|923 Sort lines by a specified word number]]
  +
*[[VimTip667|667 Working with CSV files]] sort by CSV field
  +
*[[VimTip128|128 Use Unix command-line tools in Windows]] links to download GNU sort for Windows
  +
*[[VimTip648|648 Uniq - Removing duplicate lines]] techniques to remove duplicate lines
   
  +
==References==
3) Go to last line of range to be sorted
 
  +
*{{help|:sort}}
   
 
==Comments==
4) Issue command from marker (a) to here as follows:
 
   
  +
{{Todo}}
:'a,.!sort
 
  +
*Probably need some general <code>:sort</code> command info.
  +
*Give examples of numeric sort and using regex sort.
  +
*Clean up my "see also" list. It's useful now for a comprehensive list of related tips, some of which need work. At least should add a note on point of tip.
  +
*If we're going to mention an external sort tool, we may as well include the following with a brief explanation. Vim could do this, but only with a complex regex. Or perhaps better, mention it in [[VimTip374]] or [[VimTip923]] in "see also". <code>-k2</code> sorts on the second field (word by default).
  +
<pre>
 
:!sort -k2
  +
</pre>
   
 
 
 
 
Hope this little reminder helps.
 
}}
 
 
== Comments ==
 
Use "V" and highlight the lines you want (instead of marks), then :!sort.
 
 
'''Anonymous'''
 
, March 9, 2006 7:34
 
 
----
 
----
  +
This misguided snippet was added recently:
Note that for vim &lt;7, this uses the external sort program.
 
This has some consequences:
 
   
  +
:delimit the column using some char here I have | symbol as delimiter, once did with that you can use below command to sort specific column use -n if u want to sort numeric and its working on some version of vi and not on ubuntu vi :(
- the program must be installed (which it usually is)
 
- options can be passed to it
 
   
  +
<pre>/|.*|/ | sort</pre>
which means you can do (for example)
 
:!sort -n
 
to sort numerically,
 
:!sort -k2
 
to sort on the second field, etc
 
   
  +
:used to match a patern |.*| used to match words delimited between || and | as piping commend and sort to sort
'''Anonymous'''
 
, March 9, 2006 14:21
 
----
 
Just to point out that sort is a *nix utility. windows users will need to get sort.exe from
 
http://www.cygwin.com/
 
or http://unxutils.sourceforge.net/
 
   
  +
This is wrong and should never work. Here's what it is actually doing:
To sort whole file, and delete duplicates
 
:%!sort -u
 
   
  +
<code>/|.*|/</code>: jump to the next line that has two '|' characters in it, anywhere
the ! here means access external utility
 
   
  +
<code>|</code>: command separator, this lets you start a new command on the current line
   
  +
<code>sort</code>: do a default sort of the entire buffer
   
  +
Basically this is the equivalent of typing <code>:%sort</code>.
zzapper
 
, March 10, 2006 4:03
 
----
 
Check [http://vimplugin.sf.net/cgi-bin/help?tag={{urlencode:eval-examples}} :help eval-examples]
 
   
  +
Now, what you CAN do, is provide a pattern that the <code>:sort</code> command will skip over and ignore at the start of every line while sorting. For example, to sort based only on text after the last '|' character on the line (what I think was intended by the example), you'd do this:
It has (as an example) a vim function called :Sort by Robert Webb that doesn't require an external sort utility.
 
   
  +
<pre>
- Karthick
 
 
:sort /^.*|/
 
  +
</pre>
'''Anonymous'''
 
, March 12, 2006 19:37
 
----
 
See also [[VimTip305]], [[VimTip374]], and [[VimTip588]].
 
 
mfo--AT--sympatico.ca
 
, March 13, 2006 10:53
 
----
 
To remove duplicate lines from a sorted list (make each line unique):
 
 
:%s/^\(.*\)\(\n\1\n\)\+/\1/g
 
 
 
org.vim--AT--pooryorick.com
 
, July 14, 2006 11:20
 
----
 
<!-- parsed by vimtips.py in 1.304864 seconds-->
 
 
to remove duplicates from a sorted list use uniq is simpler:
 
 
:%!sort|uniq
 
 
is a binary installed almost everywhere
 
----
 

Revision as of 04:16, 7 May 2020

Tip 1166 Printable Monobook Previous Next

created 2006 · complexity basic · author Robert Stovall · version 7.0


Vim has a very powerful built-in sort utility, or it can interface with an external one. In order to keep only unique lines in Vim, you would:

:{range}sort u

Yes, it's that simple.

You could create a range in advance, such as 'a,. (from mark 'a' to the current line) or you could create one on-the-fly using visual selection by pressing ':' in visual mode, after selecting the text you wish to sort, to get a range of '<,'> on the command line.

If you like using an external sort utility instead, you can do it just as easily. For example, Unix sort, removing duplicate lines:

:{range}!sort -u

Many other systems also have an external sort utility, but the options and capabilities will differ. It is probably better to use the built-in Vim sort unless you are looking for a specific feature of the external sort (or using an old Vim without the :sort command).

Examples

Sort in reverse

:%sort!

Sort, removing duplicate lines

:%sort u

Sort using the external Unix sort utility, respecting month-name order

:%!sort -M

("respecting month-name order" means January < February < ... < December)

Numeric sort

:sort n

(this way, 100 doesn't precede 20 in the sort)

Sort subsections independently, in this example sort numbers between "start" and "end" markers

:g/start/+1,/end/-1 sort n

Sort only specific lines using ranges

sort lines 296 to 349, inclusive

:296,349sort

Sort by pattern

When working with Javascript ES6, it may be useful to sort your imports

import './ProjectTemplateEditModal.scss';
import * as _ from "lodash";
import Moment from 'moment';
import React from 'react';
import { Button, Col, Modal, Row, Label } from 'react-bootstrap';
import { CurrencyControl } from '../../Core/Components/Controls';
import { DynamicModalMixin } from '../../Core/Components/Modals';
import { ProjectTemplateStore } from '../Stores/ProjectTemplateStore';
import { StoreBinder } from '../../Core/Utils/StoreBinder';
import { TextAreaControl } from '../../Core/Components/Controls/TextAreaControl';
import { TextBoxControl } from '../../Core/Components/Controls/TextBoxControl';
import { TooltipWrapper } from '../../Core/Components/Tooltips/TooltipWrapper';
import { withRouter } from 'react-router';

It is possible to pass a regex expression to sort. Any lines that do not match the expression will be sorted normally, while lines that do match will be sorted on the text that *follows* the expression.

:{range}sort /\/[A-z]/

This will organize your imports relative to the "package" they are related to:

import * as _ from "lodash";
import Moment from 'moment';
import React from 'react';
import { Button, Col, Modal, Row, Label } from 'react-bootstrap';
import { withRouter } from 'react-router';
import { CurrencyControl } from '../../Core/Components/Controls';
import { TextAreaControl } from '../../Core/Components/Controls/TextAreaControl';
import { TextBoxControl } from '../../Core/Components/Controls/TextBoxControl';
import { DynamicModalMixin } from '../../Core/Components/Modals';
import { TooltipWrapper } from '../../Core/Components/Tooltips/TooltipWrapper';
import { StoreBinder } from '../../Core/Utils/StoreBinder';
import './ProjectTemplateEditModal.scss';
import { ProjectTemplateStore } from '../Stores/ProjectTemplateStore';

You can also sort on text that *matches* the regex by including the 'r' flag, for example:

:{range}sort /\/[A-z]/ r

See also

References

Comments

 TO DO 

  • Probably need some general :sort command info.
  • Give examples of numeric sort and using regex sort.
  • Clean up my "see also" list. It's useful now for a comprehensive list of related tips, some of which need work. At least should add a note on point of tip.
  • If we're going to mention an external sort tool, we may as well include the following with a brief explanation. Vim could do this, but only with a complex regex. Or perhaps better, mention it in VimTip374 or VimTip923 in "see also". -k2 sorts on the second field (word by default).
:!sort -k2

This misguided snippet was added recently:

delimit the column using some char here I have | symbol as delimiter, once did with that you can use below command to sort specific column use -n if u want to sort numeric and its working on some version of vi and not on ubuntu vi :(
/|.*|/ | sort
used to match a patern |.*| used to match words delimited between || and | as piping commend and sort to sort

This is wrong and should never work. Here's what it is actually doing:

/|.*|/: jump to the next line that has two '|' characters in it, anywhere

|: command separator, this lets you start a new command on the current line

sort: do a default sort of the entire buffer

Basically this is the equivalent of typing :%sort.

Now, what you CAN do, is provide a pattern that the :sort command will skip over and ignore at the start of every line while sorting. For example, to sort based only on text after the last '|' character on the line (what I think was intended by the example), you'd do this:

:sort /^.*|/