ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
#!/bin/bash
bylet()
{
val=0
iter=1000000
for((i=0;i<iter;i++))
do
let val+=i
done
echo ${val}
}
other()
{
val=0
iter=1000000
for((i=0;i<iter;i++))
do
((val+=i))
done
echo ${val}
}
time bylet
time other
To reduce on the dereferences still got me the rather big difference of:
499999500000
real 0m10.552s
user 0m10.253s
sys 0m0.236s
499999500000
real 0m8.684s
user 0m8.413s
sys 0m0.234s
That's nearly 2 seconds; While the dereferencing saved 2 seconds; The difference got halved;
Changing the for loop to the old style reduced the time equally in both:
499999500000
real 0m7.705s
user 0m7.433s
sys 0m0.176s
499999500000
real 0m5.640s
user 0m5.542s
sys 0m0.089s
The difference stays 2 seconds in an iteration of 1 million simple calculations;
(( ))-style calculations are also built-in shell and in my belief generally a much stronger method.
Things get really weird when you add a little stuff:
Code:
#!/bin/bash
bylet()
{
val=0
iter=1000000
for i in {0..999999}
do
let val+=i
if [[ $val > 10000000 ]]
then
let val=5
fi
done
echo ${val}
}
other()
{
val=0
iter=1000000
for i in {0..999999}
do
((val+=i))
if ((val > 10000000 ))
then
((val=5))
fi
done
echo ${val}
}
time bylet
time other
Click here to see the post LQ members have rated as the most helpful post in this thread.
I am using the following code to read line by line from a file, however my problem is that $value=0 at the end of the loop possibly because bash has created a subshell for the loop or something similar. How can I solve this.
value=0;
while read line
do
value=`expr $value + 1`;
echo $value;
done < "myfile"
echo $value;
Note: This example just counts the number of lines, I actually desire to do more complex processing than this though, so 'wc' is not an alternative, nor is perl im afraid.
Thanks Darren.
Indeed a while loop is a block, that can be executed in a sub shell.
A sub shell is a fork of the main shell, so it inherits the variables, but there is no easy way to copy its variables back to the main shell.
It depends on the implementation:
Traditional Unix shells make it a sub shell when the block's input/output is redirected or piped.
Your work-around then is:
Code:
value=0
#save &0 in the unused &5
exec 5<&0
# read &0 from file
exec <"myfile"
while read line
do
value=...
...
done
#restore &0
exec <&5
echo $value
Posix shells, ksh, bash, zsh only make a sub shell when the block's input/output is piped (and they support the built-in $((numeric expression)).Darren's code works.
Ksh and zsh handle the last part of a pipe in the main shell, so even this one works:
Code:
value=0
cat "myfile" | while read line
do
value=...
...
done
echo $value
A few notes on that last post: I think the fipo was written by engraving letters in stone and somehow they've been able to digitize this.
Next thing: use code tags, like shown below.
Backticks are soooo 2011... use $() instead
That'd make your script look like this (changed a few more things - but essentially the same)
Code:
#!/bin/ksh
#Using Korn Shell to ease scoping of variables
value=0;
while read line
do
((value ++))
printf "\r%05d" ${value}
done < "myfile"
printf "\nValue of \$value after the loop: %d\n" ${value}
I am using the following code to read line by line from a file, however my problem is that $value=0 at the end of the loop possibly because bash has created a subshell for the loop or something similar. How can I solve this.
value=0;
while read line
do
value=`expr $value + 1`;
echo $value;
done < "myfile"
echo $value;
Quote:
I actually desire to do more complex processing than this though, so 'wc' is not an alternative, nor is perl im afraid.
And I expect that you don't need other scripting languages like Ruby as well? If so I think you just have to use Bash, as I see that you're probably using a different shell unless your file "myfile" is actually empty?. I've handled many shells already including the original bourne shell and I don't recall a shell that spawns a subprocess on a while loop unless that loop is reading a pipe but perhaps the very old ones does. Anyway if you have bash you could do it like this and it should be best enough:
Code:
#!/bin/bash
value=0
while read -r line; do ## -r to prevent backslashes to escape characters.
(( value += 1 ))
echo "$value" ## take note of the importance of placing string inside doublequotes especially when in a normal bash statement
done < "myfile"
echo "$value"
[QUOTE='Darren[UoW];711668']I am using the following code to read line by line from a file, however my problem is that $value=0 at the end of the loop possibly because bash has created a subshell for the loop or something similar. How can I solve this.
.
value=0;
while read line
do
value=`expr $value + 1`;
echo $value;
done < "myfile"
It will return the first token (the line count) only.
To automate, one method is to put above wc command in a chmod 777 script named something like CountLns.scr
and change file-in-question to $1 and put CountLns.scr thefile in a loop that feeds it files.
examples:
CountLns.scr BirthdayPartyInvites.txt ==one shot
for f in *.txt; do CountLns.scr $f; done ==process current directory
for f in `find . -name "*.txt" -print`; CountLns.scr $f; done ==process current branch.
...You can sum the script's output, redirect it to another file, or whatever suits you.
.
Normally wc -l would return number of lines followed by file name.
Using CountLns.scr BirthdayPartyInvites.txt will return just 100 if that is the number of lines in that file.
. (removed greater than sign)
sh, wc and cut are stock aids in Linux.
don't forget to have first line of script start with #!/bin/bash
(or sh in place of bash if that is your flavor)
Norseman01
Last edited by Norseman01; 06-30-2015 at 02:21 PM.
I am using the following code to read line by line from a file, however my problem is that $value=0 at the end of the loop possibly because bash has created a subshell for the loop or something similar. How can I solve this.
...(snip)
Note: This example just counts the number of lines, I actually desire to do more complex processing than this though, so 'wc' is not an alternative, nor is perl im afraid.
Thanks Darren.
================================
I useually use something like:
NLins=`wc $1 | cut - -d" " -f2`
--but you can put it in a wrapper to reduce typing.
#!/bin/bash
# Name: whatever you want to call it
# Purpose: Count Number of Lines in a (txt) file.
# by: Your_Name or Initials go here
# Date: should put at least month/year here
# Requireds: if any, they go here
# chmod 777 Whatever you named it
#
LineCount=`wc $1 | cut - -d" " -f2`
echo $LineCount
# end of file
but you can just type the "LineCount...." in wherever you please.
That includes from the command line.
(In which case substitute the actual filename,
complete with path if needed, in place of $1)
bash chmod, wc and cut are supplied verbs in Linux.
(see also man pages for bash, chmod, wc and cut.)
I am using the following code to read line by line from a file, however my problem is that $value=0 at the end of the loop possibly because bash has created a subshell for the loop or something similar. How can I solve this.
value=0;
while read line
do
value=`expr $value + 1`;
echo $value;
done < "myfile"
echo $value;
Note: This example just counts the number of lines, I actually desire to do more complex processing than this though, so 'wc' is not an alternative, nor is perl im afraid.
Thanks Darren.
How about asking your real question. Quit asking for people to solve steps to what you think is the correct solution. Tell us what your entire problem is and what you're trying to accomplish. If all you want to do is count lines in a file then use wc. If that's not what you're trying to do then stop beating around the bush and give us the real problem.
EDIT: this thread is 11 years old at this point. I don't know why people keep posting. It's confusing. Can a mod lock this thread?
I am using the following code to read line by line from a file,
...snip)
Thanks Darren.
=====================
The bottom line: end value is not right.
try this:
#!/bin/bash
#
lnno=0
#echo $lnno #use if line number increases AFTER processing.
while read aline
do
lnno=$(( $lnno + 1 )) # this line before or after processing
# processing # can make a difference. so make sure
# more processing # all commands are in sync just as the
# and more processing # same as with base 0 or base 1 in counting.
echo $lnno " " $aline # optional location just here as an example.
done <afile.txt
echo $lnno # should repeat last line number inside loop
# end of file
-----
Sample output of use with a text file. Binary files are best not printed direct.
Convert binaries to Hex or something before printing.
1
2
3 I was reading through the Complete CSS Guide and came to the Page Layout
4 Properties section. The comments on 'layer' are not definitive. It left
5 me confused. What was the author trying to say?
...
23 Computer Aided Drafting makes extensive use of LAYERS. Foundation,
24 floor, walls, wiring, piping, etc go on their respective LAYERS and for
25 good reasons.
26
27 A single element on a 2D plane is an element, not a layer. ...
... etc etc
now one can at least use the line numbers for conversation about a specific line in a text file.
Norseman01
Last edited by Norseman01; 04-17-2016 at 06:17 PM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.