I have a simple bash script that reads lines from a text file like so:

while read line; do
done < $FILE

which works fine but now I want to first parse the file using grep like so :

INPUT_file=$(grep -E 'INPUT.*ACCEPT' $FILE)

and then assign that result to the variable INPUT_file

I would like to now read lines from the variable "INPUT_file" but when I try to include in the while loop:

while read line; do
done < $INPUT_file

I get the following error:

$INPUT_file: ambiguous redirect

You would be better off using process substitution rather than a variable:

while read line; do
done < <(grep -E 'INPUT.*ACCEPT' $FILE)

(note two < characters). This avoids loading the entire grep output into memory at once to store in a variable. The grep process will be run in parallel with the loop, and the loop will see grep's output as read's input as each line prints out (up to buffering).

This will tend to be faster and use less memory than using $(...) command substitution and keeping the whole output around. It's also generally better style if you're writing a Bash-specific script, because it's explicit about what you're using the command for.

Arguably, this is a bit of an antipattern to start with - you might be better still using an ordinary pipeline for whatever processing you require, rather than while read ... and processing it in Bash, but there are valid cases for using either.


That is when here string comes into play:

while read line; do
  • this didn't work for me as it now treated INPUT_FILE as an empty file, for example if I placed a echo "$line" in the while loop, it would print nothing – tim Dec 6 '16 at 6:25

You shouldn't invoke grep in this case. All can be done using your shell only. E.g

while read -r line; do [[ $line =~ INPUT.*ACCEPT ]] && printf '%s\n' "$line"; done < your_iptables_file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.