3

Similar to Sorting lines from longest to shortest, how can I sort all of the lines in a file from shortest to longest? E.g."

This is a long sentence.
This is not so long.
This is not long.

That becomes:

This is not long.
This is not so long.
This is a long sentence.
Community
  • 1
  • 1
Village
  • 22,513
  • 46
  • 122
  • 163

5 Answers5

7

It's almost exactely the same as in the link you gave

awk '{ print length($0) " " $0; }' $file | sort -n | cut -d ' ' -f 2-

the -r option was for reversing the sort.

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
6
perl -ne 'push @a, $_ } { print sort { length $a <=> length $b } @a' input

(On my box, this runs about 4 times faster than the awk | sort | cut solution.)

Note that this uses a terrible perl idiom and abuses the semantics of -n to save a few keystrokes. It would be better to write this as:

perl -ne '{ push @a, $_ } END { print sort { length $a <=> length $b } @a }' input
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • +1. More like 7.5 times faster when tested on a 200+K logfile. The `asorti` solution was terminated because it took too long, not sure why it's so inefficient. – Thor Sep 14 '12 at 23:22
  • Followup question: http://stackoverflow.com/questions/18815105/how-does-this-perl-one-liner-in-the-bash-works – tripleee Sep 15 '13 at 17:14
  • Probably you should not confuse users, and write `perl -ne 'push @a, $_ ; END { print sort { length $a <=> length $b } @a }'` instead... – Slaven Rezic Sep 15 '13 at 20:07
  • @Slaven, I agree! Unfortunately, this -p while/loop braces hack is common enough in perl...will edit with proper disclaimers. – William Pursell Sep 16 '13 at 13:55
  • I benchmarked several solutions on a 550MB text corpus, and found that using pure perl results in a 6x speedup, vs Perl + pipes to shell commands. http://stackoverflow.com/questions/8296649/sorting-lines-from-longest-to-shortest/33511642#33511642 – Chris Koknat Nov 04 '15 at 18:07
1

Note that this solution does not perform well on large input.

You could also do the sorting within awk:

cat << EOF > file
This is a long sentence.
This is not so long.
This is not long.
EOF

sort.awk

# Only find length once
{ len = length($0) }     

# If we haven't seen this line before add it to the lines array 
# and move on to next record
lines[len] == "" { lines[len] = $0; next }

# A duplicate, append to the previous record
{ lines[len] = lines[len] RS $0 }

END {
  # lines array is sorted according to the indices, the sorted
  # indices are stored in the indices array
  asorti(lines, indices)
  for(key in indices)
    print lines[indices[key]]
}

Run like this:

awk -f sort.awk file

Or as a one-liner:

< file awk '{ len = length($0) } lines[len] == "" { lines[len] = $0; next } { lines[len] = lines[len] RS $0 } END { asorti(lines, indices); for(key in indices) print lines[indices[key]] }'

Output:

This is not long.
This is not so long.
This is a long sentence.
Zombo
  • 1
  • 62
  • 391
  • 407
Thor
  • 45,082
  • 11
  • 119
  • 130
1

With POSIX Awk:

{
  c = length
  m[c] = m[c] ? m[c] RS $0 : $0
} END {
  for (c in m) print m[c]
}

Example

Zombo
  • 1
  • 62
  • 391
  • 407
1

Another perl implementation:

perl -ne 'print length($_)." $_"' file | sort -n | cut -d ' ' -f 2-

$_ is the current line, similar to awk's $0

Chris Koknat
  • 3,305
  • 2
  • 29
  • 30