4

I need to sort a file based on the number of chars in the first column.

I have no idea on how to go about this. (On Linux, so sed/awk/sort is available).

An example:

.abs is bla bla 12
.abc is bla se 23 bla
.fe is bla bla bla
.jpg is pic extension
.se is for swedish domains

what I want is to sort these lines, based on the length of the first column in each line. Some of the lines start with 4 characters, some start with 3, or 2. I want the result to be something like:

.fe is bla bla bla
.se is for swedish domains
.abs is bla bla 12
.abc is bla se 23 bla
.jpg is pic extension

Is this even possible?

migrated from serverfault.com Jan 31 '13 at 22:14

This question came from our site for system and network administrators.

1

You can first add another column with count of characters with awk, do sort and then strip added column:

awk '{printf "%d %s\n", length($1), $0}' file.txt | sort -n -k1,1 | sed -E -e 's/^[0-9]+ //'

  • Also see this answer on Stack Overflow. You don't need printf or sed in there, actually. – Wildcard Jan 12 '16 at 9:10
0

You can do it with basic shell tools, but if Perl is available, you can express your requirement more directly:

perl -l -e 'print sort {@a = split(/ /, $a, 2); @b = split(/ /, $b, 2);
                        length($a[0]) <=> length($b[0])} <>'

With the Schwartzian transform (more efficient for large input):

perl -l -e 'print map {$_->[0]}
                  sort {length($a->[1]) cmp length($b->[1])}
                  map {[$_, split(/ /, $_, 2)]} <>'

If you have Python, the code is more verbose but a bit clearer:

python -c 'import sys;
lines = sys.stdin.readlines();
lines.sort(key=lambda line: len(line.split()[0]));
sys.stdout.writelines(lines)'
0
$ awk -vOFS='\t' '{ print length($1), $0 }' file.in | sort -k1,1n -k2,2 | cut -f2-
.fe is bla bla bla
.se is for swedish domains
.abc is bla se 23 bla
.abs is bla bla 12
.jpg is pic extension

This sorts the file file.in by the length of the data in the first column, then lexicographically on the actual data of the first column (this was not specifically requested in the question, but provides a nice touch to the result).

The awk code will create tab-delimited output like

4       .abs is bla bla 12
4       .abc is bla se 23 bla
3       .fe is bla bla bla
4       .jpg is pic extension
3       .se is for swedish domains

and this is what sort sorts, on the first column (numerically) and then the second column (lexicographically). The cut then removes the first column from this.

Your Answer

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