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.
I need to be able to read a line of user input and store that into an array. Currently, what I have technically works, but not the way I want it to.
Code:
echo "How many documents do you want to create?"
read COUNT
echo "Enter the names of the documents you wish to build surrounded by single quotes, separated by spaces."
echo "See the following format: '01 Financial Statement ct' '02 Insurances ct' '03 Tax Returns ct'"
read -ea DOCUMENTS
echo "${DOCUMENTS[0]}"
echo "${DOCUMENTS[1]}"
THE PROBLEM:
1) Even when I surround what I'd like each element of the array to be by single quotes, I still have to use a backslash to escape the space between words within the single quotes. And then when I view the output, it shows the single quotes at the beginning and end, which is not desirable.
Problem 2
In attempts to not have the single quotes show up, I didn't use them and only escapes backslashes between spaces of the same elements. This output is better, but still not practical as I'm sure other users will put slashes in the wrong place, etc.
INPUT 2:
Code:
01\ Financial\ Statement\ ct 02\ Insurances\ ct
OUTPUT 2:
Code:
01 Financial Statement ct
02 Insurances ct
Is there a way to separate array elements by using a comma instead, negating the need for backslashes? Or a way to use the single quotes to isolate the elements from each other, without requiring the backslashes as well??
But really, the big problem here is that a single iteration of read only works on a single "line" of input (as delimited by the "-d" option). Then to split the line into an array, you have to change the IFS variable to define the field breaks.
More properly, to capture multiple lines like this you should use a loop.
And it's no use adding quotes to the input. Once the text is stored in the variable, the shell parsing order ensures that they will always be treated as literal. You'd have to parse the line manually in order to handle them.
I think what I would do is something more like this:
Code:
echo "Enter the names of the documents you wish to build."
echo "Press 'enter' after each entry. When finished, enter the word 'done'."
n=0
while true; do
read -e -p 'Enter a document name or "done": ' name
case $name in
[Dd][oO][nN][eE]) break ;;
*) documents[n++]=$name ;;
esac
done
echo "${documents[@]}"
This also adds another benefit in that you can also add tests to validate each entry by other criteria (e.g. file exists, or matches a certain pattern) before continuing.
P.S. Environment variables are generally all upper-case. So while not critical, it's good practice to keep your own user variables in lower-case or mixed-case, to help differentiate them.
Last edited by David the H.; 05-07-2012 at 12:42 PM.
Reason: minor corrections and additions
Ok, the IFS change is going to work best for what I need. Here's the updated code as of now. Thanks to everyone for the help so far.
Code:
1 echo "How many documents do you want to create?"
2 read COUNT
3
4 echo "Enter the names of the documents you wish to build surrounded by single quotes, separated by spaces."
5 echo "See the following format: '01 Financial Statement ct' '02 Insurances ct' '03 Tax Returns ct'"
6
7 OIFS=$IFS #Saves original field separator
8 IFS=',' read -ea DOCUMENTS
9
10 for i in {0..$((COUNT-1))}
11 do
12 echo "${DOCUMENTS[$i]}"
13 done
14
15 IFS=$OIFS #Restores original field separator
Oh for goodness sakes, no. Never use eval for something like this. That's like using a howitzer to hunt mosquitoes.
There are several (much) more appropriate ways to handle looping through arrays.
Code:
for i in "${DOCUMENTS[@]}"; do
echo "$i"
done
for i in "${!DOCUMENTS[@]}"; do
echo "${DOCUMENTS[i]}"
done
for (( i=0; i<=COUNT; i++ )); do
echo "${DOCUMENTS[i]}"
done
printf '%s\n' "${DOCUMENTS[@]}"
Sorry if David and I came across a little harsh ... not trying to pick on you as we are aware that you were new. Just trying to help you move away from starting a bad habit
From an user interface perspective, instead of asking how many documents the user intends to specify up front, you could just accept new document names from the user, until they supply an empty line:
Code:
DOCUMENTS=()
while read -p "Document $[${#DOCUMENTS[@]}+1]: " DOCUMENT ; do
# Break the loop if DOCUMENT is empty
[ -n "$DOCUMENT" ] || break
# Append DOCUMENT to DOCUMENTS array.
DOCUMENTS[${#DOCUMENTS[@]}]="$DOCUMENT"
done
printf 'You specified %d documents:' ${#DOCUMENTS[@]}
printf '\t\047%s\047\n' "${DOCUMENTS[@]}"
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.