2

Given input with mixed text and numbers (w/o leading zeros), how can I get it sorted in the "natural" order? For example, given the following input (hostnames):

whatever-1.example.org
whatever-10.example.org
whatever-11.example.org
whatever-12.example.org
whatever-13.example.org
whatever-2.example.org
whatever-3.example.org
whatever-4.example.org
whatever-5.example.org
whatever-6.example.org
whatever-7.example.org
whatever-8.example.org
whatever-9.example.org

I would like this output:

whatever-1.example.org
whatever-2.example.org
whatever-3.example.org
whatever-4.example.org
whatever-5.example.org
whatever-6.example.org
whatever-7.example.org
whatever-8.example.org
whatever-9.example.org
whatever-10.example.org
whatever-11.example.org
whatever-12.example.org
whatever-13.example.org

EDIT

I should have mentioned that in addition to the "whatever"s there would also be

thingaroo-#.example.org
      .
      :

blargh-#.example.org
      .
      :

...etc...

Thanks!

3

If you have GNU coreutils ≥ 7.0, then you can use version sort. This is lexicographic order except that sequences of digits are ordered according to their value as an integer in decimal notation.

sort -V
  • This appears to be the simplest answer. – John Hascall Mar 12 '16 at 17:02
2

That particular style of input could be successfully be sorted with

sort -t - -nk2,2

but it doesn't really generalize to all sorts filenames, if that's what you are looking for.

  • Upvoted for being the only one to mention this is not a general solution. – Wildcard Mar 11 '16 at 7:51
  • This answer was very helpful in coming up with what I really wanted (see my question edit and answer). Thanks! – John Hascall Mar 11 '16 at 13:34
2

Sorry, I didn't give all the info needed in my original question. All the answers were useful to me in coming up with what I really wanted. What I ended up using was:

sort -t- -k1,1 -k2,2

where:

-t-       divide the hostnames into fields using dash (-) rather than spaces
-k1,1     the first sort key is the first field (from 1 to 1), a normal sort
-k2,2     the second key is the second field using a numeric (n) sort
          (the field includes the ".example.org" but the numeric sort
          seems to cope find with the trailing non-number chars)

this gives the result:

blargh-1.example.org
    :
blargh-13.example.org
thingaroo-1.example.org
    :
thingaroo-17.example.org
whatever-1.example.org
    :
whatever-13.example.org
1

Assuming whatever in your text can vary, you need to use sort with the following options:

-t, --field-separator=SEP use SEP instead of non-blank to blank transition

k, --key=POS1[,POS2] start a key at POS1 (origin 1), end it at POS2 (default end of line)

-V, --version-sort natural sort of (version) numbers within text

sort -t "-" -k 2 -V < [filename]
  • This worked to sort them all by the numbers. All the "1"s, then all the "2"s etc. This was not what I wanted here, but still good to know. – John Hascall Mar 11 '16 at 13:18
0
sort -t- -k2n file

whatever-1.example.org
whatever-2.example.org
whatever-3.example.org
whatever-4.example.org
whatever-5.example.org
whatever-6.example.org
whatever-7.example.org
whatever-8.example.org
whatever-9.example.org
whatever-10.example.org
whatever-11.example.org
whatever-12.example.org
whatever-13.example.org

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.