How to extract elements in a field using a number

Hi,

I face difficulty where the number which I grep before I would like to use it as number to grep again in another file.

For example in file 1, I extract the second field and assign to variable "char" in a while loop. And then, I grep again this char to get i and j.

char=`echo "${LINE}"| awk '{print $2}'`

echo $char

i=`grep -n "^$char" b.txt|awk '{print $2}'`
j=`grep -n "^$char" b.txt|awk '{print $3}'`

I tried to use $i and $j for operation such that q=$i+$j; however, it gives me error.

Besides, I tried to grep again this "char" in another file using grep -n char$ file2 but it doesnt work. (In a typical example : grep -n element$ filename should give us the exact line of element)

Please advise. Thanks.

-Jason

Do you want to add them numerically?

q=`echo $i + $j | bc`

or literally?

q=$i$j

do you have sample files?

Are you sure i and j are numbers?

Hi Zelp,

These are numbers. And basically in a while loop, I do not declare awk. Most of the time, I only do echo which in the end I could not use printf.

Sample code:-

#!/bin/bash

cat a.txt|while read LINE
do

char=`echo "${LINE}"| awk '{print $2}'`

#echo $char
i=`grep -n "^$char" b.txt|awk '{print $2}'`
j=`grep -n "^$char" b.txt|awk '{print $3}'`
k=`grep -n $char$ c.txt|awk '{print $1}'`

echo $i
echo $j
echo $k

q=`echo (($j)/($i+$j))|bc `

echo $q

#awk '{
#q=$j/($i+$j)}

#END{

#printf("q is %d", $q);
#}'

done

I have error in echo where it doesnt allow me to perform computation. I am thinking to use AWK whihc is put easier but I could not because it invovles multiple files to read and compare.

Please advise what is the best solution for this. Thanks!

-Jason

Did you not see my

q=`echo $i + $j | bc`

?

Yeap porter,
But my computation is complex which is

$j/$i+$j.

Please advise. Thanks.

-Jason

j=`echo \( $j / $i \) + $j | bc`

Hi porter,

Still has error of:-
5
6

7
2
2

3
2
2

3
(standard_in) 1: parse error

My sample code is:-
#!/bin/bash

cat a.txt|while read LINE
do

char=`echo "${LINE}"| awk '{print $2}'`

#echo $char
i=`grep -n "^$char" b.txt|awk '{print $2}'`
j=`grep -n "^$char" b.txt|awk '{print $3}'`
k=`grep -n "^$char" c.txt|awk '{print $1}'`
q=`echo \( $j / $i \) + $j | bc`

echo $i
echo $j
echo $k
echo $q

done

My sample input file (let say for illustration purpose here) is

a.txt
aa 108
bb 109
cc 110
ddd 100

b.txt
108 5 6
110 2 2
109 2 2

c.txt

2  0.959341 109
3  0.959341 108
4  0.797717 367
5  0.788534 83

I dont see any problem in here though...please advise. Thanks.

As always I recommend debugging scripts using

(a) strategically placed statements that print the value of variable

(b) using "#!/bin/sh -x" at the start of the script

(c) the equivalent of asserts, where you exit if some condition is not met, see (a)

Hi Porter,

I debug the script and found out that:-

i) ++ echo '6/(' 5 '+6)'
++ bc
+ q=0

Does it means bc will round down the value? How can I get the exact value of division in this case?

ii) As I raised before, given the file has quite similar number.It will still print out all the possible number that found.

++ awk '{print $1}'
+ k='2:
3:'

This basically print the positions of file in c.txt(below) when 108 is grepped. Which means k=`grep -n "$char" c.txt|awk '{print $1}'` is not working to grab exact number.

2 0.959341 109
3 0.959341 108
4 0.797108 367
5 0.788534 83

iii)the (standard_in) 1: parse error comes in when the bc tries to calculate non value from (non match entry). Do you have any idea how to prevent the q to be calculate when the grep returns empty?
I tried to insert while and if inside but it returns me
./grep2.bash: line 49: syntax error near unexpected token `done'
./grep2.bash: line 49: `done '

Please help. Thanks.

-Jason

select b.col2 i, b.col3 j, c.col1 k, (b.col3/b.col2)+b.col3 q
from a.txt a, b.txt b, c.txt c
where a.col2 = b.col1
and a.col2 = c.col3

See how simple & clean? Now you just need to upload these three files into three database tables :slight_smile:

On a serious note, use FILENAME variable in awk to differentiate between multiple files. Using awk is much better than wrestling with shell constructs/commands - particularly if your files are big. The performance gains are massive.

HTH

"if/then/fi" springs to mind.

Regarding the calculations appearing like integer, try changing the formula to

j=`echo \( $j.00000 / $i.00000 \) + $j.00000 | bc`

Hi,

Do you mean have this code in the bash itself?
I have error of

./grep4: line 3: syntax error near unexpected token `i,'
./grep4: line 3: `select b.col2 i, b.col3 j, c.col1 k, (b.col3/b.col2)+b.col3 q'

Rgrds,
Jason

Sorry Jason - that was my lame try at humor - do not execute that :slight_smile:

Try porter's solution & post the results.

Hi porter,

The formula is supposed to be ($j)/($i+$j) not the other way round.Anyway, I still cant get the calculation to float which in debug mode it gives

++ echo '(6.00000)/(5.00000' '+6.00000)'

which output value q=0 rather than float.

My code is:-
q=` echo \($j.00000\)\/\($i.00000 +$j.00000\)|bc`

Please advise. Thanks.

-jason

$ i=5
$ j=6
$ k=`echo $i $j |awk '{printf("%f",($2/($1+$2)))}'`
$ echo $k
0.545455

try

echo scale=4\; $j + \( $j + $i \) | bc

Hi porter,

I tried before on scaling method and i do not know how to turnaround especially in my scenario.

Thanks. I managed to use rikxik formula and it is working. The reason is because i am actually parsing the whole echo to a variable rather than echo alone.

However, on the other note, I still havent resolve the grep problem where it still return me any value which is matching the number rather than exact number (grep -n number$ filename).Still finding what character I missed out to isolate the "$" so that the number is uniquely grabbed from the file.

If you have any idea, let me know.
Thanks.

Rgrds,
Jason