LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   bash: incrementing variable outside scope of loop (https://www.linuxquestions.org/questions/programming-9/bash-incrementing-variable-outside-scope-of-loop-4175545643/)

schneidz 06-17-2015 12:39 PM

bash: incrementing variable outside scope of loop
 
Code:

[schneidz@hyper 2015-06-13]$ head test.*
==> test.ksh <==
#!/bin/bash

s=1; cat test.lst | while read line
do
 echo $s - $line
 ((s++))
done
echo total lines = $s


==> test.lst <==
there
are
4
lights !!!
[schneidz@hyper 2015-06-13]$ ./test.ksh
1 - there
2 - are
3 - 4
4 - lights !!!
total lines = 1

how do i get it to print 4 ?

rknichols 06-17-2015 01:00 PM

Your problem is that the use of the pipe causes the whole while loop to run in a separate process. Nothing in that child process can affect variables in the parent. This will work:
Code:

#!/bin/bash

s=0
while read line
do
 ((s++))
 echo $s - $line
done <test.lst
echo total lines = $s

Note that I've changed the initialization and re-ordered the lines to avoid an off-by-one error in the reported total.

schneidz 06-17-2015 01:18 PM

^ thanks, not quite solved. lets say instead of a file. the input of the loop is a string of commands:
Code:

#!/bin/bash

dw=some.file
s=0
while read line
do
 ((s++))
 echo $s - $line
done < awk 'BEGIN { FS="\n" ; RS=""} /^isos:/ {print $0}' $dw | tail -n+2
echo total lines = $s


smallpond 06-17-2015 02:28 PM

You need to put variable s in the same shell as the while loop. Use parens to make subshell:

Code:

#!/bin/bash

awk 'BEGIN { FS="\n" ; RS=""} /^isos:/ {print $0}' $dw | tail -n+2 | (
  s=0
  while read line
  do
    ((s++))
    echo $s - $line
  done
  echo total lines = $s
)


grail 06-17-2015 03:13 PM

nah ... just use process substitution:
Code:

#!/bin/bash

dw=some.file
s=0
while read line
do
 ((s++))
 echo $s - $line
done < <(awk 'BEGIN { FS="\n" ; RS=""} /^isos:/ {print $0}' $dw | tail -n+2)
echo total lines = $s

Important note, the space is required between the 2 < signs


All times are GMT -5. The time now is 10:36 AM.