15

I'm interested to find out the line number of the longest line from a file.

For example, if I have a file with the following content:

lalala
tatatata
abracadabra
mu mu mu

how can I write a bash script that will give me an output something like this: 3 -> abracadabra?

1

5 Answers 5

12

You could use awk to print the length of each line (length()) and the line number (NR), then reverse (-r) sort the result by number (-n):

$ awk '{ print length(), NR, $0 | "sort -rn" }' tmp.txt
10 3 abracadabr
8 4 mu mu mu
7 2 tatatat
6 1 lalala

To show just the first line:

$ awk '{ print length(), NR, $0 | "sort -rn" }' tmp.txt | head -n 1
10 3 abracadabr
3
  • @user214965 please see my update, the line number displayed is the second number in the result.
    – Attila O.
    Nov 12, 2013 at 9:57
  • What if there are 2 lines with the same maximum length? Nov 12, 2013 at 10:09
  • @RaduRădeanu good point. +1 for wc -L, I didn't know about that argument. It is very useful indeed.
    – Attila O.
    Nov 12, 2013 at 14:31
11

You don't need a script for doing this. A simple command is enough:

egrep -n "^.{$(wc -L < filename)}$" filename

This will work even when you have two or more lines with the same maximum length.

If you want that the output to be exactly in this form: 3 -> abracadabra, then use:

egrep -n "^.{$(wc -L < filename)}$" filename | sed 's/:/ -> /'

References:

4
  • 3
    @don.joey: that's the power of unix. Simple commands, that can work together. here, he looks for "^.{n}$", ie any line that, between the beginning of line (^) and its end ($) has exactly n characters (.{n}). Then he just needs to find n: for this he uses a GNU-ism, "wc -L filename" (note that this is not posix) which returns the length of the longest line of filename. So he greps any line that has the longest length. $(cmd) is replaced by the output of cmd. Nov 12, 2013 at 16:26
  • 1
    @OlivierDulac Great comment. Nov 12, 2013 at 16:27
  • Even better, you can also add (e.g.) -C 3 to the grep options to get a few lines before and after for context Mar 14, 2020 at 20:20
  • This doesn't work for very long lines, gets grep: Regular expression too big. Of course, when I'm looking for long lines in a log so I can improve logging by making them shorter, it's the ones that are too big that I'm looking for Nov 10, 2022 at 18:06
4

A O(N) can be achieved with a perl one liner :

perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max'

usages (where machin is a file name)

cat machin | perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max'

or

perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max' machin

or (less clear but shorter)

perl -ne 'if(length>length$m){$m=$_};END{print$m}' machin
2
  • Much, much more efficient. Thanks! Was looking for it.
    – test30
    Jan 13, 2016 at 17:50
  • 1
    Works with huge files +1
    – h3xStream
    Oct 29, 2017 at 3:08
0

O(n) For machines, for example OpenWRT, where perl is not available, @awk@ version might be useful.

awk 'length > l {l=length;line=$0} END {print line}' FILE

or python:

python -c "print max(open('$file', 'r'), key=len)"
0

Radu's answer is perfectly sufficient and prefered, although if you want more explicit and shell-based solution, then you could use the following script:

#!/bin/bash
longest_length=0
longest_string=0
while IFS= read -r line || [ -n "${line}"]
do
    if [ "${#line}" -gt "${longest_length}" ]
    then
        longest_length="${#line}"
        longest_string="$line"
    fi
done < "$1"

echo "${longest_string}"

Usage: ./find_longest.sh input.txt

Example:

$ cat input.txt                                                          
1 2 
2 3 a a a a
4 5 6 
1 1 1 5

$ ./find_longest.sh input.txt                                            
2 3 a a a a

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .