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
  • 20,305
  • 41
  • 116
  • 158

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
  • 19,274
  • 14
  • 81
  • 118
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
  • 190,037
  • 45
  • 260
  • 285
  • +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
  • 55
  • 342
  • 375
Thor
  • 42,211
  • 10
  • 116
  • 125
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
  • 55
  • 342
  • 375
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,082
  • 2
  • 28
  • 29