1

I had the following bash script which was working fine.

#!/bin/bash

OUTFILE=somefile.txt
(
./runnable input << EOF
2
4
EOF
) > $OUTFILE

but later i had the need of changing arguments. there are 100 files in a directory, each file has two numbers. these two numbers need to be fed to the above script. 100 files have data in them like this:

2,4
9,2
4,2

so i changed the script to the following but this does not seem to work.

#!/bin/bash

OUTFILE=file3.txt
(
while read line
do
./runnable input << EOF

#following gets first number before comma
test=$(echo `expr index "$line" ,` )
echo ${line:0:($test-1)}
line=$(echo ${line:$test})

#following gets second number after comma
test=$(echo `expr index "$line" ,` )
echo ${line:0:($test-1)}
line=$(echo ${line:$test})

EOF
done < file_with_values
) > $OUTFILE

what can i be doing wrong?

2
  • Do you want to give runnable pairs of numbers, or just one at a time? Aug 5, 2009 at 12:08
  • While this doesn't help you with your problem, you should know that you can nest $() so you don't need backticks at all. But you don't need to use expr or the line it's in or the following two lines. To get the part before the comma: echo "${line%,*}" and the part after the comma: echo "${line#*,}" but as Balázs Pozsár said, you can't have commands inside a here doc. Aug 14, 2009 at 3:36

4 Answers 4

2

You cannot write a script inside an inline data block (<< EOF)

Try something like this:

OUTFILE=file3.txt

while IFS=, read a b; do
    echo "first number: $a"
    echo "second number: $b"

    # you can call runnable here, for example if you want to give it one number at a time:

    echo "$a" | ./runnable input
    echo "$b" | ./runnable input

    # or something like this:

    ./runnable "$a" "$b"

done >$OUTFILE
1

Try splitting the line easy way by making an array out of the line you read, like this (where your_line is the line you read from the file).

OIFS=${IFS}
IFS=','
your_line=(${your_line})
IFS=${OIFS}

Now ${your_line[0]} is the first number, ${your_line[1]} the second. You can echo them, add them, whatever. This will probably work fine.

The whole scripts would become something along the lines of:

#!/bin/bash

cat FILE_WITH_VALUES | while read your_line; do

    OIFS=${IFS}
    IFS=','
    your_line=(${your_line})
    IFS=${OIFS}

    echo ${your_line[0]} ${your_line[1]} | ./runnable_input >> OUTPUT_FILE

done

Downside is that this will start runnable_input 100 times (once for every line). On a reasonably fast machine, 100 runs for such a small input would not matter though, unless runnable_input depends on getting 100 lines a time.

1

Preprocess your 100 files into 1 datafile then work with that

#!/usr/bin/bash

OUTFILE=xyzzy
(
while read line 
do
./runable $line
done <datafile
)>$OUTFILE
0

Try this script,

#!/bin/sh
IFS="
"
for i in $( sed 's|,| |g' file_with_values );
do
    ./runnable $i
done > file3.txt

You must log in to answer this question.