Variable setting help please

L=0

cat test.sh | while read line
do

L='expr $1 + 1'
echo $L

done

echo $l

>>> the echo $L at the end produces 0 but i actually want it to produce the number of lines - any idea why this is happening?

If you trying to find out the number of lines in a file, use this simple approach

wc -l < filename

Vino

Or if you want to use the while loop here it is

#! /bin/sh

L=0

while read line
do
L=$((L+1))
done < filename

echo "Total # of lines = $L"

Vino

What is $1 and $l ??

I think the problem is with $l (small ) as it is not defined .

When you pipe into a loop, sh actually
starts a subshell and runs the loop in that.
However any changes to variables in this
subshell can not be propagated back to the parent.

Hi,

This produces an error: L=$((L+1))

also i only mixed up the 1's and L's when copying it onto the forum

cheers

Try the modified RHS of L

-vino

This still produces 0

Post the shell and os you are using.

And also the exact script you are running.

Just to alert you

the quotes in

L=`expr $L + 1`

are backticks. The one found above the TAB key on your keyboard.

Vino

@pixelbeat: correct! There is a difference between "$l" (lowercase L) and "$L" (uppercase L) the OP seems not to be aware of.

Another error is the line:

 L='expr $1 + 1' 

Apart from the fact that "expr" shouldn't be used any more and that it should be replaced by "(( .... ))" "L" is set to some value given at the commandline (the "$1") increased by 1. Since the value of the commandline doesn't change it gets set to the same value over and over again

bakunin

#!/bin/sh

L=0

while read line
do

L=`expr $L + 1`
echo $L

done < dinseh.sql

echo $L

I think pixelbeat is right.
In this case, most of shell folks a subshell to run the loop block.
try ksh.

Another distant possibility

--dinseh.sql is empty--

:confused:

What does

wc -l <dinseh.sql 

give ?

Vino

At least you last version should be working.

Still there are some things to say about:

/switches ranting, style-aficionado mode on

Don't use the backticks any more, this is outdated style and not necessary in the Korn shell. If you want to execute a command, then put the output of that command into a variable instead of

 x=`command` 

use

 x="$(command)" 

Second, instead of "expr" or "let" you should use the "(( .. ))" construct, which is easier to read and encouraged by David Korn. Instead of

 x=$(expr $x + 1)
and
let x=1

better write:

 (( x = x + 1)) or (( x+= 1 ))
and
(( x = 1  ))

Yes, I already know i can be a PITA, no neeed to point that out. ;-))

/switches ranting mode off, reverting back to a humble person

bakunin

I think yes.

But the whole .sh script runs in a fork'ed subshell. Since the script runs in a subshell, $L ( within the context of the script) will retain the value and echo should output it right.

Once you are out of the script, the subshell ceases to be. And hence no more $L in the parent shell.

vino

#!/bin/sh

L=0

test()
{
while read line
do

l='expr $L + 1'
echo $L

done

echo $L
}

test < test.sh

  • The entire while loop runs in a subshell because of the pipe
  • Variable values set inside while loop not available after while loop

A solution:

L=0

cat test.sh | { while read line
do

L='expr $1 + 1'
echo $L

done

echo $L

}

Notice the braces. They put the variables in the local subshell.