3

I have an executable, say it's called a.out. It takes two lines of input after a prompt --

> ./a.out 
> give me input-1: 0 0 10
> give me input-2: 10 10 5
> this is the output: 20 20 20

I can store the inputs in a file (input.txt) and redirect it to a.out, the file looks like this --

0 0 10
10 10 5

and I can call a.out like --

> ./a.out < input.txt
> give me input-1: 0 0 10 give me input-2: 10 10 5
> this is the output: 20 20 20

Now I want to store multiple inputs in that file and redirect into a.out. The file will look like this with 2 inputs --

0 0 10
10 10 5
0 0 20
10 10 6

and I am writing a bash script like --

exec 5< input.txt
while read line1 <&5; do
      read line2 <&5;
      ./a.out < `printf "$line1\n$line2"` ;
done

It does not work, how do I do that?

2
  • It might help to describe more specifically what about your final attempt doesn't work exactly. (From a general high quality question perspective if nothing else.) Commented Sep 22, 2014 at 17:18
  • Much safer to use printf '%s\n' "$line1" "$line2"; that way you don't introduce bugs if anything in line1 or line2 reads as a format string. Commented Sep 24, 2014 at 16:30

1 Answer 1

5

< requires a file name containing content, not the content itself. You probably just want to use a pipe:

exec 5< input.txt
while read line1 <&5; do
    read line2 <&5
    printf "%s\n%s\n" "$line1" "$line2" | ./a.out
done

or a process substitution:

exec 5< input.txt
while read line1 <&5; do
    read line2 <&5
    ./a.out < <(printf "%s\n%s\n" "$line1" "$line2")
done

You don't need to use a separate file descriptor, though. Just redirect standard input to the loop:

while read line1; do
    read line2
    printf "%s\n%s\n" "$line1" "$line2" | ./a.out
done < input.txt

You might also use a here document (but note the indentation):

while read line1; do
    read line2
    ./a.out <<EOF
$line1
$line2
EOF
done < input.txt

or a here string:

while read line1; do
    read line2
    # ./a.out <<< $'$line1\n$line2\n'
    ./a.out <<<"$line1
$line2"
done < input.txt

The newline can be included using the special $'...' quoting, which can specify a newline with \n', or the string can simply have an embedded newline.


If you are using bash 4 or later, you can use the -t option to detect the end of the input, so that a.out can read directly from the file.

# read -t 0 doesn't consume any input; it just exits successfully if there
# is input available.
while read -t 0; do
    ./a.out
done < input.txt
Sign up to request clarification or add additional context in comments.

6 Comments

A HERESTRING would also work (without needing a sub-shell).
I was just about to add a here string, but then decided to just add a here document, since embedding a newline in the here string requires either Yet Another New Syntax ($'...\n...') or something that looks almost exactly like a here doc anyway.
OK, I caved on the here string, since I realized process substitution was probably also worth mentioning.
-t would be my preferred option.
Copying printf "$line1\n$line2\n" from the OP is bad juju -- if anything in either of those lines is a format string...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.