[SOLVED] Need some help with a Bash script
I am having a little trouble with a Bash shell script that I am working on. It is intended to read the information out of a gedcom genealogy file and determine who has lived in a particular area and output a report based upon who lived in a given area (like the different sections of a bygdebok for example). I am having a number of issues.
1) I can't seem to figure out how to get a variable to work as the index of an array. For example, I am trying to use the variable $individual to count which individual is being read in from the .ged file, and once that is figured out, next I will read in the individual's name, so I would like to create an array of names using the variable Code:
$individual Code:
name[$individual]=$lineoftext; Code:
$lineoftext Quote:
2) If I try to echo a statement with multiple variables, the first variable is getting ignored, and I can't figure out why. For example, if my line of code says something like Code:
echo $individual" "$lineoftext Code:
echo "$individual $lineoftext" Code:
$individual Code:
$lineoftext Code:
$individual Code:
echo $individual Code:
$individual Here is an example of the file format I'm dealing with: Code:
0 @I1039@ INDI Here is the code I have so far in my shell script: Code:
#!/bin/bash Code:
./generate.sh Code:
Cecilia Gudmundsdotter Leervig Any suggestions appreciated. |
Code:
if [[ ${lineoftext:0:1} == "0" ]] Code:
category=${lineoftext:0:1} Code:
if [[ $lineoftext == *\@\ INDI* ]] Code:
if [[ $lineoftext =~ *\@\ INDI* ]] Quote:
|
Quote:
Code:
# Shell script to generate bygdebok sections by location from gedcom files formatted in UTF-8. Quote:
So, the first thing I need help on is how to use my variable $individual (stores the number of person being read in) as the index in the name array, as the code Code:
name[$individual]= Also, if I change the code to say: Code:
#!/bin/bash Code:
#!/bin/bash Code:
Åmund Torsteinsson Osvåg Code:
1039 Åmund Torsteinsson Osvåg |
Right so you do know that bash arrays can only have numeric indices?
|
You are not defining $individual inside the last if statement, and you can't use a name as an index in an array, only numbers. Maybe if you could create a hash then it might work.
|
Quote:
Quote:
|
From your first post
Code:
if [ $category == 1 ] Code:
Cecilia Gudmundsdotter Leervig Quote:
A hash is a construction like an array, but instead of having numeric indices, you have named keys. So to access a value from a hash you might request the value stored in the hash name -> key "name" have a look at http://tldp.org/LDP/abs/html/ (use Ctrl + F and search for hash) |
I looked over the information you gave me about hash, and I think that looks like a much better way to go about it and I think it will solve the array problem once I learn how to use hash. Thanks for that information.
Still having problems outputting the number stored in $individual. You expressed doubt that a number is being stored in $individual. If we use the following code: Code:
#!/bin/bash Code:
0001 |
Bash v4 has associative arrays, which means you can use strings as index elements.
To tell the truth, I'm having a bit of a hard time following this thread. I don't have the energy currently to work through all the code. :( But the initial array stuff looks ok to me. It looks like the main problem is getting the variables set properly. Make sure you're watching your quoting. One thing that might help is to start by declaring the "$individual" variable as an integer before using it. You can also try initiating the array name as well. I believe this is necessary for associative arrays. I ran a quick test with the following, which simply outputs a list of $RANDOM numbers. Perhaps it will help. Code:
#!/bin/bash Code:
declare -A array #declare as an associative array |
I really like the idea of using the associative arrays and that is really the idea I was originally aiming for, but both my server that will in the end be running the script and my laptop which I am writing and testing the script on have Bash version 3.2.39, so I'll probably have to learn to use the hash method since I don't have Bash 4.0.
|
You might have a carriage return character in $individual.
It can be caused by using files in Linux which have been edited in Windows. Demonstration :- Code:
individual=1234$'\r' # $'\r' is a carriage return character. |
You were absolutely right about the carriage return being a huge part of the problem. I changed the line that said
lineoftext=`echo $lineoftext | sed "s/\@\ INDI// g"`; to say lineoftext=`echo $lineoftext | sed "s/\@\ INDI\r// g"`; and suddenly there is no error message. Funny how things seem so complicated and it usually turns out to be something so simple... Thank you so much for that suggestion! So simple, and I never would have thought of it. And of course the .ged file did originally come from a Windows environment since that is what runs the Family Tree Maker software that created it. I had converted it from Western enconding to UTF-8 so it would work with Bash in Linux, but never thought about carriage returns. Now I can probably use the first example that David gave to set up arrays. The second example he gave won't work for me since I don't have Bash v4, but I tried the first example, and it worked flawlessly with my version of Bash, so I think I can set things up that way. I'll play around with it a bit and let everyone know what I come up with and how it works out. I'm thinking problem solved though. |
Problem is officially solved.
New code that works correctly: Code:
#!/bin/bash Code:
./generate.sh Code:
... All suggestions were helpful, good suggestions, but the two suggestions that ended up solving the problem were David the H.'s first code example about how to do arrays with variables as the index and Kenhelm's idea to check for carriage returns. Thanks so much! |
Glad I could help you out. Those pesky windows line-endings always seem to throw things for a loop, don't they?
One comment on your code. I think you're relying too much on if-then statements. Bash has a couple of variations that can make your code cleaner. First there's "if-elif-else" Code:
if [[ ${lineoftext:0:1} == "0" ]]; then Code:
Code:
category=${lineoftext:0:1} |
Quote:
|
All times are GMT -5. The time now is 09:49 PM. |