How to sort strings that contain a common prefix and suffix numerically from Bash?

28,096

Solution 1

Use ls -lv

From the man page:

-v     natural sort of (version) numbers within text

Solution 2

Try the following:

sort -t '_' -k 2n
  • -t '_' (sets the delimiter to the underscore character)
  • -k 2n (sorts by the second column using numeric ordering)

DEMO.

Solution 3

If available, simply use sort -V. This is a sort for version numbers, but works well as a "natural sort" option.

$ ff=$( echo some.string_{100,101,102,23,24,25}_with_numbers.in-it.txt )

Without sort:

$ for f in $ff ; do echo $f ; done
some.string_100_with_numbers.in-it.txt
some.string_101_with_numbers.in-it.txt
some.string_102_with_numbers.in-it.txt
some.string_23_with_numbers.in-it.txt
some.string_24_with_numbers.in-it.txt
some.string_25_with_numbers.in-it.txt

With sort -V:

$ for f in $ff ; do echo $f ; done | sort -V
some.string_23_with_numbers.in-it.txt
some.string_24_with_numbers.in-it.txt
some.string_25_with_numbers.in-it.txt
some.string_100_with_numbers.in-it.txt
some.string_101_with_numbers.in-it.txt
some.string_102_with_numbers.in-it.txt

Solution 4

In the general case, try the Schwartzian transform.

Briefly, break out the number into its own field, sort on that, and discard the added field.

# In many shells, use ctrl-v tab to insert a literal tab after the first \2
sed 's/^\([^0-9]*\)\([0-9][0-9]*\)/\2   \1\2/' file |
sort -n |
cut -f2-

This works nicely if the input doesn't have an obvious separator, like for the following input.

abc1
abc10
abc2

where you would like the sort to move the last line up right after the first.

Share:
28,096
AWE
Author by

AWE

Updated on February 20, 2020

Comments

  • AWE
    AWE over 4 years

    Here is a list of files:

    some.string_100_with_numbers.in-it.txt
    some.string_101_with_numbers.in-it.txt
    some.string_102_with_numbers.in-it.txt
    some.string_23_with_numbers.in-it.txt
    some.string_24_with_numbers.in-it.txt
    some.string_25_with_numbers.in-it.txt
    

    Now I would like to sort it numerically. Starting with *23* and ending with *102*.

    I have tried -n and -g. -t does not help in these messy strings.

    Can I ignore leading strings to the number with an option or do I have to be clever and script?

  • Jonathan Leffler
    Jonathan Leffler over 11 years
    Note that the -v option to ls is a GNU extension; since you're on Linux, that's OK, but it is not portable to other systems necessarily.
  • AWE
    AWE over 11 years
    Exactly! it was the k option that I had forgotten and was "hidden" in the man pages.
  • becko
    becko about 9 years
    is there an analogous command with find instead of ls (or perhaps piping to sort)?
  • interestinglythere
    interestinglythere about 9 years
    On Mac, can you can brew install coreutils and use gls.
  • tripleee
    tripleee almost 8 years
  • tripleee
    tripleee almost 8 years
    @becko find always traverses the tree in a deterministic order and outputs the files in the order it finds them.
  • Muhamed Huseinbašić
    Muhamed Huseinbašić about 5 years
    @becko sort has -V option which is "natural sort of (version) numbers within text"