Reputation: 594
I have a script that outputs file paths (via find) :
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
How can I list them in Bash so that they are in ascending numeric order based on the number at the end and regardless of the version ( 1.2, 1.2.3 or 1.2.3.4)
Ps : the something
part can eventually contain a dash.
Desired output :
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
I used a temporary sentinel character to delimit the number at the end but it's a little bit complicated in my case.
Upvotes: 2
Views: 1593
Reputation: 289535
Extract the number at the end, prepend it to all the lines, sort numerically and finally delete that number:
sed -r 's/(.*)([^0-9])([0-9]+)$/\3\1\2\3/' file | sort -n | sed 's/^[0-9]*//'
With your input, this returns:
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
I think this is the Schwartzian transform.
By pieces:
$ sed -r 's/(.*)([^0-9])([0-9]+)$/\3\1\2\3/' a
16/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
1/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
5/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
2/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
10/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
#^
#note the numbers here
$ sed -r 's/(.*)([^0-9])([0-9]+)$/\3\1\2\3/' a | sort -n
1/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
2/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
5/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
10/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
16/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
# ^
# now it is ordered
$ sed -r 's/(.*)([^0-9])([0-9]+)$/\3\1\2\3/' a | sort -n | sed 's/^[0-9]*//'
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
Upvotes: 4
Reputation: 2091
If you can ensure that you will never have a '#' character in your file, you can try:
sed -e 's/something/#/g' filename.txt | sort -t# -k2 -n | sed -e 's/#/something/g'
Upvotes: 1
Reputation: 785008
You can use this sed + sort + awk
:
sed -E 's/.*[^0-9]([0-9]+)$/\1 &/' file | sort -n | awk '{print $2}'
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something1
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something2
/foo/bar/example/foo/bar/example/foo-bar-example/1.2-something5
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3.4-something10
/foo/bar/example/foo/bar/example/foo-bar-example/1.2.3-something16
Upvotes: 3