[BASH] How to read multiple lines from a text file?
For example, I have a text file with data which lists numerical values from two separate individuals
Code:
Person A Thanks. |
Are the number of lines for each person fixed? Are there any other lines in the file or other variations possible compared to the above?
One possibility would be to simply load the whole file into an array. Bash v.4 even has a new mapfile (syn: readarray) built-in command for doing just that. Or for older versions you can use cat: Code:
mapfile arrayname <file Simple integer arithmetic can then be done with $((...)). Code:
echo "$(( arrayname[1] + arrayname[20] ))" The only difficulty is that you need to know which index numbers to use, which is why I asked if the input is predictable. |
The text file is fixed. Meaning there will be just 2 persons A and B, and they will each have 12 values under them.
I noticed that you are Location is listed in Japan .. and Im hoping that you and any of your family and friends are okay in this time.. my Prayers going out to you and everybody in this tough time.. |
Moved: This thread is more suitable in Programming and has been moved accordingly to help your thread/question get the exposure it deserves.
|
I'd suggest this then:
Code:
IFS=$'\n' Edit: For bash v4's mapfile, you can do this: Code:
mapfile -t p1array < <(grep -A 12 "Person A" file) And thank you for your concern. But I'm half the country away from the quake and wasn't directly affected at all. The strength was only about a 4 here. In fact, I was on my bike at the time heading for a job and didn't notice a thing. I did feel the large aftershock 30 minutes later, however, which set everything rattling again for some time. I'm sitting at home now watching the aftermath on the news and those tsunami images are scary stuff. |
I am a bit confused. Sorry. I am quite new to programming and Bash. Ive had around 2 days worth of experience.
I am fairly average with arrays, and I have not heard of the IFS command.. Also, I maybe did not mention clearly that both the PersonA and PersonB would be in one text file.. Sorry if I have set confusion upon you ! |
So not sure what else you might need to do, but as a sum example:
Code:
awk '/Person/{a=$0}/[0-9]/{sum[a]+=$0}END{for(x in sum)print "Total for",x,"is",sum[x]}' file |
Sorry, I just had noticed you updated your post to include the mapfile and its really great!
I just have one more question in regards to this. How would I go about creating a NEW text file, using the above p1array and p2array, which would show the total of each line.. For example the first value for PersonA is 100, while the first value of PersonB is 1200 .. the sum would be 1300 How can I get it to show that Line 1 = 1300 into a new file.. |
Quote:
IFS is the internal field separator environmental variable. It controls what characters bash views as "word" separators. It's set for space/tab/newline by default. But when you want it to ignore spaces, you can set it to newline only and it will break up the text based on lines instead. And yes, I realized they're in the same file. That's why I used grep to grab each individual entry. the -A 12 option means that grep will output the matching string you give it, plus the 12 lines following it. |
Quote:
Code:
echo "The sum of the first lines is $(( p1array[1] + p2array[1] ))" >> newfile Here are a few useful bash scripting references: http://www.linuxcommand.org/index.php http://tldp.org/LDP/Bash-Beginners-G...tml/index.html http://www.tldp.org/LDP/abs/html/index.html http://www.gnu.org/software/bash/manual/bashref.html |
Quote:
But you have helped me much more! I do have one more question but I will try to solve that on my own before bugging you again! :hattip: |
And just for the alternative:
Code:
awk -ventry=1 '/Person/{a++;i=0}/[0-9]/{_[a,++i]=$0}END{print "The sum for entries",entry,"is",_[1,entry]+_[2,entry]}' file >> newfile |
I've tried some googling and reading tutorials, but can't seem to answer my problem..
I understand to use decimals in BASH is not possible .. and we have to use bc, awk or dc .. I've tried to implement it but without success, I keep getting : syntax error: invalid arithmetic operator (error token is ".50") I won't have any decimals, but it would be nice to add to my knowledge incase in the future I would have to do such a task. |
It would help if we could see the command that's generating the error.
I only know the most basic use of bc, but that's all you need here. Simply build the expression you want to evaluate using echo and pipe it through bc. Code:
echo "${p1array[1]} + ${p2array[1]}" | bc Code:
echo "${p1array[1]} ${p2array[1]}" | awk '{print $1 + $2}' Code:
awk -v p1="${p1array[1]}" -v p2="${p2array[1]}" 'BEGIN{ print p1 + p2 }' Finally, you can redirect the output of any of the above directly to a file as before, or you can capture the output of any command into a variable using $(..). Code:
result="$( echo "${p1array[1]} + ${p2array[1]}" | bc )" |
All times are GMT -5. The time now is 12:55 AM. |