Thank you all for your responses, and my apologies on not providing a sample input format. My "verses" is not in hash form, though the chapters are (which I don't know how to change just yet, but it doesn't matter as I've used the $a <=> $b syntax to sort them). I hadn't figured out how to handle the ones like "1 Corinthians", "2 Thessalonians" yet but that was on the "to do" list. The perldsc, "Hash of arrays" seems to be what I wanted and I've now successfully printed out that when I first parse it (line 173 - marked in comment), but I seem to be having difficulty in saving the information properly, so that when I try to retrieve it a second time (line 270 - also marked in comment), my arrays are "empty"(original part 2 of my question). Do I need to start 'bless'ing verses? Here's the code and sample input:

The Project Gutenberg EBook of The Bible, Douay-Rheims, Old and New
Testaments, Complete
This eBook is for the use of anyone anywhere at no cost and with
almost no restrictions whatsoever. You may copy it, give it away or
re-use it under the terms of the Project Gutenberg License included
with this eBook or online at www.gutenberg.net
Title: The Bible, Douay-Rheims, Old and New Testaments, Complete
The Challoner Revision
Author:
Release Date: December 17, 2004 [EBook #8300]
Language: English
Character set encoding: ISO-8859-1
*** START OF THIS PROJECT GUTENBERG EBOOK DOUAY-RHEIMS BIBLE ***
Produced by David Widger from PG etext #1581 prepared by Dennis
McCarthy, Atlanta, Georgia and Tad Book, student, Pontifical North
American College, Rome
THE HOLY BIBLE
Translated from the Latin Vulgate
Diligently Compared with the Hebrew, Greek,
and Other Editions in Diverse Languages
THE OLD TESTAMENT
First Published by the English College at Douay
A.D. 1609 & 1610
and
THE NEW TESTAMENT
First Published by the English College at Rheims
A.D. 1582
With Annotations
The Whole Revised and Diligently Compared with
the Latin Vulgate by Bishop Richard Challoner
A.D. 1749-1752
HISTORY
This e-text comes from multiple editions of Challoner's revised Douay-
Rheims Version of the Holy Bible. In 1568 English exiles, many from
blah, blah, blah...
Oxford, established the English College of Douay (Douai/Doway), Flande+rs,
The notes included in this electronic edition are generally
attributed to Bishop Challoner.
CONTENTS
The Old Testament
Book of Genesis
Book of Exodus
Book of Leviticus
...
BOOK: GENESIS
This book is so called from its treating of the GENERATION, that is,
of the creation and the beginning of the world. The Hebrews call it
BERESHIT, from the Word with which it begins. It contains not only
the history of the Creation of the world; but also an account of its
progress during the space of 2369 years, that is, until the death of
JOSEPH.
Genesis Chapter 1
God creates Heaven and Earth, and all things therein, in six days.
1:1. In the beginning God created heaven, and earth.
1:2. And the earth was void and empty, and darkness was upon the face +of
the deep; and the spirit of God moved over the waters.
1:3. And God said: Be light made. And light was made.
Genesis Chapter 2
God rests on the seventh day and blesses it. The earthly paradise, in
which God places man. He commands him not to eat of the tree of
knowledge. And forms a woman of his rib.
2:1. So the heavens and the earth were finished, and all the furniture
of them.
2:2. And on the seventh day God ended his work which he had made: and +he
rested on the seventh day from all his work which he had done.
He rested, etc... That is, he ceased to make or create any new kinds o+f
things. Though, as our Lord tells us, John 5.17, "He still works",
viz., by conserving and governing all things, and creating souls.
BOOK: EXODUS
The Second Book of Moses is called EXODUS, from the Greek word EXODOS,
which signifies going out: because it contains the history of the goin+g
out of the children of Israel out of Egypt. The Hebrews, from the word+s
with which it begins, call it VEELLE SEMOTH: These are the names. It
contains transactions for 145 years; that is, from the death of Joseph
to the erecting of the tabernacle.
Exodus Chapter 1
The Israelites are multiplied in Egypt. They are oppressed by a new
king, who commands all their male children to be killed.
1:1. These are the names of the children of Israel, that went into Egy+pt
with Jacob: they went in every man with his household:
1:2. Ruben, Simeon, Levi, Juda,
Exodus Chapter 2
Moses is born and exposed on the bank of the river; where he is taken +up
by the daughter of Pharaoh, and adopted for her son. He kills an
Egyptian, and flees into Madian; where he marries a wife.
2:1. After this there went a man of the house of Levi; and took a wife
of his own kindred.
2:2. And she conceived, and bore a son: and seeing him a goodly child,
hid him three months.
Exodus Chapter 3
God appears to Moses in a bush, and sends him to deliver Israel.
3:1. Now Moses fed the sheep of Jethro, his father in law, the priest +of
Madian: and he drove the flock to the inner parts of the desert, and
came to the mountain of God, Horeb.
3:2. And the Lord appeared to him in a flame of fire out of the midst +of
a bush: and he saw that the bush was on fire, and was not burnt.
The Lord appeared... That is, an angel representing God, and speaking +in
his name.
BOOK: LEVITICUS
This Book is called LEVITICUS, because it treats of the Offices,
Ministries, Rites and Ceremonies of the Priests and Levites. The Hebre+ws
call it VAICRA, from the word with which it begins.
Leviticus Chapter 1
Of holocausts or burnt offerings.
1:1. And the Lord called Moses, and spoke to him from the tabernacle o+f
the testimony, saying:
1:2. Speak to the children of Israel, and you shall say to them: The
man among you that shall offer to the Lord a sacrifice of the cattle,
that is, offering victims of oxen and sheep:

john-kos-computer:bible john$ ./chapters.pl sample_bible.txt
4 books
----------------------------------------------------------------------+----------
3 books
GENESIS has 2 chapters
1:1. In the beginning God created heaven, and earth.
1:2. And the earth was void and empty, and darkness was upon the face +of
the deep; and the spirit of God moved over the waters.
1:3. And God said: Be light made. And light was made.
2:1. So the heavens and the earth were finished, and all the furniture
of them.
2:2. And on the seventh day God ended his work which he had made: and +he
rested on the seventh day from all his work which he had done.
EXODUS has 3 chapters
1:1. These are the names of the children of Israel, that went into Egy+pt
with Jacob: they went in every man with his household:
1:2. Ruben, Simeon, Levi, Juda,
2:1. After this there went a man of the house of Levi; and took a wife
of his own kindred.
2:2. And she conceived, and bore a son: and seeing him a goodly child,
hid him three months.
3:1. Now Moses fed the sheep of Jethro, his father in law, the priest +of
Madian: and he drove the flock to the inner parts of the desert, and
came to the mountain of God, Horeb.
3:2. And the Lord appeared to him in a flame of fire out of the midst +of
a bush: and he saw that the bush was on fire, and was not burnt.
LEVITICUS has 1 chapters
1:1. And the Lord called Moses, and spoke to him from the tabernacle o+f
the testimony, saying:
1:2. Speak to the children of Israel, and you shall say to them: The
man among you that shall offer to the Lord a sacrifice of the cattle,
that is, offering victims of oxen and sheep:
Please enter the Book, Chapter, and/or Verse you want: GENESIS
Got book GENESIS
GENESIS: You're looking for: GENESIS
joining chapter 1 verses
-1 verses
joining chapter 2 verses
-1 verses
Please enter the Book, Chapter, and/or Verse you want:

I have not had much time to look at your post (it is kinda big; a small, self-contained, runnable code example will help your fellow monks find problems, and may very well help you to find problems just by preparing it!) and may not be able to do so thoroughly today, but a few things strike me about the code quoted above, which includes the problematic line 270:

The expression $#{$bible{$qbook}{$chapter}{'verses'}} will yield -1 if the referenced array is empty. That this is the case is shown by the following print statement print "$#{$bible{$qbook}{$chapter}{'verses'}} verses\n";
which produces "-1 verses". The expression 0 .. -1 produces an empty range, which means that the loop body, line 270, is never executed. You have to go back and find where this array was emptied, or else why nothing was ever put into it in the first place.

An expression like $#array or $#$array_reference evaluates to the highest array index, not to the number of elements, verses in this case, in the array.

Thanks for your prompt response and patience/wisdom. I didn't expect so many quick and detailed responses during the Christmas season. I've broken down my exceedingly long 300 lines or so into several subroutines to make for better readability.

I found the answer to my memory problems - "make an anonymous copy" via a post from Randal Shwartz. At: http://www.stonehenge.com/merlyn/UnixReview/col30.html. I basically needed to put [] around my @verses array so that I create a copy of it when I point my hash reference there.

In terms of the foreach stylistic point (@{$bible...), that was sort of the syntax I was looking for for my join, but my issue had been that I had an empty array. Would not the following be even cleaner? Comments on efficiency?

That seems to be working for me now. I may have future questions regarding my little project but now I have some experience regarding "too little" and "too much" so I'll try to ensure I follow your advice of making it "just right" and using &ltreadmore&gt as appropriate.

In terms of the foreach stylistic point (@{$bible...), that was sort of the syntax I was looking for for my join... Would not the following be even cleaner? Comments on efficiency?

print join("\n\n",@{$bible{$qbook}{$chapter}{'verses'}});

The salient difference between a statement like print join("\n\n",@{$bible{$qbook}{$chapter}{'verses'}});
and a loop like foreach my $verse (@{$bible{$qbook}{$chapter}{'verses'}}) { print $verse, "\n\n"; }
is that the join built-in creates a copy in memory of all the concatenated elements of the array, and the for-loop does not. In fact, the for-loop does not even create a copy of any element of the array, but rather aliases $verse to each element in turn.

I vaguely recall that the Bible consists in fewer than 900,000 words. Even with commentaries included and using the hairiest possible UTF character set, it's hard for me to imagine the whole thing being longer than a few score MBs as a single string, and this is easily accomodated by Perl (in addition to whatever is still sitting in the array) on any remotely modern machine/OS I'm aware of. Furthermore, certain things, e.g., multi-line regex operations, often become quite simple with such a string. OTOH, you're only talking about join-ing all the verses of a single chapter, amounting to a still relatively short string, and modern operating systems are quite well adapted to I/O operations involving many, relatively short 'lines' of data.

IOW, the join-versus-for-loop question is one of scalability, and the task you are dealing with does not seem likely to encounter scaling problems. (If you were dealing with genomics problems, the situation would be different; such problems very often involve processing files with many MB or GB of large records, so one must be very sensitive to scaling issues.)

So for me, the chief considerations in dealing with your code would be readability and maintainability, with efficiency a distant third and scalability nowhere in sight. Based on these considerations, my personal preference would be the for-loop: it's highly idiomatic and familiar. (But I can't help saying that my guess would be that the for-loop would also be slightly more efficient in terms of speed and certainly in terms of memory usage.)

HTH, and best wishes for the new year.

Update: If you want to throw readability and maintainability to the four winds and go with cute, the following might be the most efficient of all: { local $, = "\n\n"; print @{$bible{$qbook}{$chapter}{'verses'}}; }

When putting a smiley right before a closing parenthesis, do you:

Use two parentheses: (Like this: :) )
Use one parenthesis: (Like this: :)
Reverse direction of the smiley: (Like this: (: )
Use angle/square brackets instead of parentheses
Use C-style commenting to set the smiley off from the closing parenthesis
Make the smiley a dunce: (:>
I disapprove of emoticons
Other