If sort --version-sort
is not available, split into 2 fields: field 1 = leading non-digits, and field 2 = integer number, and print the fields with TAB between them. Then use sort
on 2 TAB-delimited fields, then remove the TAB. Connect by pipes to avoid I/O overhead. Here is an example with a minimal slice of the data from the OP, plus a few additional records:
echo 1 10 2 11 DATA DATA1 DATA10 DATA11 DATA2 FRA FRA1 FRA10 FRA11 FRA2 | \
xargs -n1 | \
perl -lne 'print join "\t", /(\D*)(\d*)/' | \
sort -k1,1 -k2,2n | \
perl -pe 's/\t//'
Prints:
1
10
11
2
DATA
DATA1
DATA2
DATA10
DATA11
FRA
FRA1
FRA2
FRA10
FRA11
DETAILS:
The perl one-liners use these command line flags:
-e
: tells Perl to look for code in-line, instead of in a file.
-n
: loop over the input one line at a time, assigning it to $_
by default.
-l
: strip the input line separator ("\n"
on *NIX by default) before executing the code in-line, and append it when printing.
-p
: same as -n
, but also print
the line at the end of each loop (eliminates explicit print
).
Within the first one-liner, \d
is any digit (0-9), and \D
is any non-digit. Each of these patterns is repeated 0 or more times (using *
). The two patterns are captured using parentheses and returned as a LIST
of two fields, which are joined on a TAB and printed.
The second Perl one-liner simply removes the first TAB is finds with nothing (empty string) and prints the line.
To sort
on 2 fields, these options are used:
-k1,1
: sort on field 1 ASCIIbetically. Then:
-k2,2n
: if field 1 is the same, sort on field 2 numerically (-n
option).
Note that the field number is repeated twice (e.g., 1,1
), to prevent sorting on the rest of the line and limit the sort to just this column number.