Ideas for while loop

idealy, i'd like to do something like this:

while read line
do
        echo $line
done < $(egrep error /var/log/syslog)

but when i do, i get an unexpected response. i.e.


cat test:

#!/bin/sh

while read line
do
        echo $line
done < $(egrep error /var/log/syslog)

## ./test

when i run the above, while it does print each line, at the very end, it prints the following error message:

i get an error at the last line that says:

: File name too long

i'm using the above method because it appears to be faster than this:

egrep error /var/log/syslog | while read line
do
        echo $line
done

What's wrong with a simple

egrep error /var/log/syslog

???

1 Like

I think the while loop is expecting a filename.

you could redirect the output to a file

egrep error /var/log/syslog > /tmp/error.out

while read line
do
        echo $line
done < /tmp/error.out

rm /tmp/error.out
1 Like

Assuming the echo $line is nothing more that a place holder test, if your shell supports it.

while read line
do
    echo $line
done < <(egrep error /var/log/syslog)
1 Like

Hello SkySmart,

Could you please try following and let me know if this helps.

while read line
do
        echo $line
done < "$(egrep error /var/log/syslog)"

Thanks,
R. Singh

1 Like

i tried this. got the same error.

The loop expects a file after the redirect of stdin ( < ), which command substitution will not provide (unless the file happens to contain a single filename). Try a redirect through a pipe:

egrep error /var/log/syslog | 
while read -r line
do
  printf "%s\n"  "$line"
done

or in bash / ksh93 / zsh you can also provide a constructed file like this (process substitution) if you want:

while read -r line
do
  printf "%s\n"  "$line"
done < <(egrep error /var/log/syslog)

Edit : Just noticed Aia already suggested something similar to the latter option..

1 Like

Assuming that your shells supports it, you can get away from calling an external program like egrep for such a simple match

while read -r line
do
  [[ $line =~ error ]] && echo $line
done < /var/log/syslog

Again, this is all assuming that the echo $line is nothing more that a place holder or test for what it would be a real `do something meaningful', otherwise is silly.

1 Like

Hello SkySmart,

We can follow simple way here too by redirecting the egrep output to a file and then we can take input from that file as follows. Offcourse finding other ways is good too for our learning.

egrep error /var/log/syslog > Error_Details.txt
while read line
do
     echo "$line"
done < Error_Details.txt

Or we can simply use egrep error /var/log/syslog in script itself :).

Thanks,
R. Singh

1 Like

I'm still confused as to what the end requirement is. If you want to extract records to display on the screen, the egrep by itself will do that. If you need to use a loop to do something else with the records, then save the IO cost, the disk space and the time with:-

egrep error /var/log/syslog | while read line
do
     echo "Processing line \"$line\""
     # Do whatever else here......
done

You will need to be careful that any nested loops don't gobble up your input to this loop.

Anyway, what are you trying to achieve?

Kind regards,
Robin

1 Like

i have to run a while loop and it is very important to me that i find the method that is the quickest.

The methods below appear to be the fastest, but, while they loop through the file, they error out at the end, complaining about file name too long:

while read line
do
    echo $line
done < <(egrep error /var/log/syslog)
while read line
do
    echo $line
done < "$(egrep error /var/log/syslog)"

I don't understand. The first method should work (if the shell supports it) and cannot complain that the filename is too long (unless this is literally somewhere in the text of your syslog file :slight_smile: )
If the shell does not support it, it will give a syntax error.

The second method is wrong and will not work and will produce that error.

--
BTW. it is best to quote $line ( echo "$line" )

Hi,
Another way:

while read line
do
    echo "$line"
done <<_EOF
$(egrep error /var/log/syslog)
_EOF

Regards.

1 Like