Bash script find longest line/lines in several files

Hello everyone...
I need to find out, how to find longest line or possibly lines in several files which are arguments for script. The thing is, that I tried some possibilities before, but nothing worked correctly.
Example
when i use:

awk ' { if ( length > L ) { L=length ;s=$0 } }END{ print L,"\""s"\"" }' "file"

it will only print 1 longest line. But what if there are 2 or more lines with exact length? Or there are similar lines in different files?

 awk '{print length, $0}' | sort -nr | head -1

this is my second through, but same problem as above and i don't know how to make it.

Thanks for any solutions

Try this:

awk 'length==L{S[++i]=$0} length > L{L=length; delete S; S=$0}END{ for(j=1;j<=i;j++)print L,"\""S[j]"\"" }' infile

---------- Post updated at 11:29 ---------- Previous update was at 11:25 ----------

or

awk 'length==L{p=p RS L FS "\""$0"\""} length > L{L=length; p=L FS "\""$0"\""}END{ print p}' infile
1 Like
awk 'NR==FNR{L=(length>L)?length:L;next} length==L' infile infile
1 Like

OK, thank you for you time, it works nice :b:

---------- Post updated at 06:38 PM ---------- Previous update was at 11:17 AM ----------

May i ask, is it possible to do same thing without awk?

Shell version
maxlength=0
while IFS= read -r line
do
if [ ${#line} -eq $maxlength ]; then
p="${p}
${#line} \"$line\""
elif [ ${#line} -gt $maxlength ]; then
p="${#line} \"$line\""
maxlength=${#line}
fi
done < infile
echo "$p"

1 Like

Thank for that, i really appreciate that. But now something more difficult. I have written a bash script which should find the longest line or lines from all of the files which are arguments for script. If there are no argument, standart input is selected... And script should have help. So my question is, why this my script isn't working at all?

#! /usr/local/bin/bash2

print_help ()
{
    echo "The longest file or files"
    echo "-h shows help"
}
riadok=""

for i in  "$@"; do
        case "$1" in
        -h)  print_help
              exit 0
              break
              ;;
        *)   break
              ;;
        esac
        if ["$0" -gt 0]
        then
                riadok="$(awk 'length==L{p=p RS L FS "\""$0"\""} length > L{L=length; p=L FS "\""$0"\""}END{ print p}' $0)"
                pole=("${pole[@]}" "$riadok")
        fi
        shift
done

for i in "${pole[@]}"; do
        echo "$i"
done

exit 0

Presuming /usr/local/bin/bash2 exists on your system, this will not work:

if ["$0" -gt 0]

there should be spaces and quotes have no business in a numerical context

if [ $0 -gt 0 ]

But seeing if $0 is greater than -0 makes no sense. Perhaps you mean

if [ $# -gt 0 ]

also: case $1 should be case $i and so you really want to break out of the for loop with a break statement, you mix an array pole with a variable assignment, etc.
I think you need to have a thorough look at your script...

1 Like

Well, i am bit confused... So i make changes you was writing... Script isn't working, so you are right, i need to check it... Thanks a lot... And that array.
I need to put the the longest line or lines into the array... Well, i thought that it could be like this

 
riadok="$(awk 'length==L{p=p RS L FS "\""$0"\""} length > L{L=length; p=L FS "\""$0"\""}END{ print p}' $0)"   ;    pole=("${pole[@]}" "$riadok")

And if this is not working, how can i put that lines into array?

I a, having a hard time trying to figure out what you are trying to do. You mention using reading standard input, but I see no read statements. Besides that would not even be possible, at least you could only determine the longest line in standard input, not in multiple files.

Why would this not work:

print_help ()
{
    echo "The longest line in file or files"
    echo "-h shows help"
}

for i in  "$@"; do
  case "$1" in
     -h)  print_help
          exit 0
  esac
done

awk 'length==L{p=p RS L FS "\""$0"\""} length > L{L=length; p=L FS "\""$0"\""}END{ print p}' "$@"
1 Like

It looks like i didn't tell clearly... Sorry for that... The input could be files, or nothing and in that case i should use stdin. Then should script find the longest possible line or eventually lines. Of course, -h could be there to echo help. I rewrite some of that rubbish that there was before... Now, my scritp looks like this....

#! /usr/local/bin/bash2

print_help ()
{
    echo "the longest line or lines in stdin or file or files"
    echo "-h show help"
}
riadok=""

for i in  "$@"; do
        case "$i" in
        -h)     vypis_helpu
                exit 0
                ;;
        *)
                riadok=$(awk 'length==L{r=r RS L FS ""$0""} length > L{L=length; r=L FS ""$0""}END{ print r}' "$i")
                pole=("${pole[@]}" "$riadok")
                ;;
        esac
        shift
done

for i in "${pole[@]}"; do
        echo "$i" | sort -n | tail -1
done

exit 0

Now i have a problem with set the output from awk to the variable riadok and then to put riadok into array. Hope, that this is more accurate than my last comment.

---------- Post updated at 10:16 AM ---------- Previous update was at 10:15 AM ----------

So it is "the longest line or lines in stdin or file or files"

If you look at my suggestion, I believe it does everything you require. You can use it like this, using command line parameters

./script infile*

or like this, using stdin

cat infile* | ./script

i tried to use awk inside of for to ensure, that awk will be executed for every file, that comes in. And then, the longest line or possible lines should be written to the variable. So in the and, i should have array of strings with the longest lines from all files... And from that array i choose the longest..

---------- Post updated at 10:27 AM ---------- Previous update was at 10:24 AM ----------

it gonna be automatic test and i shouldn't use cat... And i must figure out how to patch that for stdin inside script...

The awk already does all that it chooses the longest line(s) from all files. I just used cat as an example to generate input on stdin for the shell script, you can use any process there. Inside the script the awk statement will then either read the files provided as parameters to the script or read from stdin if not file names are provided.

1 Like

Well, i just finish testing... Awk is now good but it put all the lines into variable... So if i have 3 longest lines with same length, awk save all three to riadok... So it is not very good. But if awk find all longest lines from every file on input, how can i find the longest from the longest?

---------- Post updated at 11:14 AM ---------- Previous update was at 11:01 AM ----------

That code of yours isn't working, i tried to execute script ./script aaa bbb ccc...
and it didn't read stdin, just error message showed...

---------- Post updated at 11:34 AM ---------- Previous update was at 11:14 AM ----------

awk 'length==L{r=r RS L FS ""$0""} length > L{L=length; r=L FS ""$0""}END{ print r}' "$i"

I need to get output from this to the variable riadok. It works, when i've got files with only one the longest line in each file. But when it is more than that in single file, it put all lines into single variable. How can i fix this? I tried these options:

awk 'length==L{r=r RS L FS ""$0""} length > L{L=length; r=L FS ""$0""}END{ print r; riadok=r}' test001
awk 'length==L{r=r RS L FS ""$0""} length > L{L=length; r=L FS ""$0""}END{ print r; riadok=r; pole=("${pole[@]}" "$riadok")}' test001

But it doesn't work at all. Everytime it put all lines into single variable.

Of course it didn't read stdin. You did not provide anything on stdin. You would need for example a pipe to do that, like I did with the cat example.
And what code did you use? The one in Bash script find longest line/lines in several files Post: 302466294 ? What error message did you get?

1 Like

well, that error message was cant open file.... My fault... That automatic test provide som stdin and test it... But i wonder, how can i fix that awk, because if it is not possible, i must rewrite all this script and make it without awk. Probably it could be possible to do when i write a length of line to the line a sort it... I must chcecked it.

---------- Post updated at 07:48 PM ---------- Previous update was at 11:51 AM ----------

Ok, i finally get it... Well, i am really dumbass... I am sorry for all... My script is almost finished, i only must finish errors. So thank you, you saved my life...

---------- Post updated at 08:12 PM ---------- Previous update was at 07:48 PM ----------

Well, one problem has appeared. My kode is:

awk 'length==L{riadok=riadok RS L FS ""$0""} length > L{L=length; riadok=L FS ""$0""}END{ print riadok}' "$@"

it is in script. It will echo the number of characters from the longest line, but i need to print a number of line in file, and whole input should have a form:
Output: '<file>: <number of line> <length of line> <line>'

How can i make it without rewriting whole code?
it actually does the "length of line> <line>" But i need to force it have output in that form... Please help. I have tried to echo

"Output: '$@: '" and awk -F, '{if($2=="") print NR}'

should give numbers to lines. But how to make it at once?

You can use FILENAME and FNR for that:

awk 'length>=L{riadok=(length==L?riadok RS:x) "Output: " FILENAME FS FNR FS length FS $0} length > L{L=length}END{ print riadok}' "$@"
1 Like

It is working just nice... It now write all information i need... Except one... I need before that and after a '... How can i do that? Nearly our i tried " ' ` and nothing works... If you know how to do this, this is my last comment here...

You mean like this:

awk 'length>=L{riadok=(length==L?riadok RS:x) "Output: " q FILENAME ":" FS FNR FS length FS $0 q} length > L{L=length}END{ print riadok}' q="'" "$@"
1 Like

Looks like good idea but it show error message:
[: =: unary operator expected