LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-07-2010, 03:39 PM   #1
zulsolar
LQ Newbie
 
Registered: Mar 2005
Location: Buenos Aires, Argentina
Distribution: Slackware, Solaris 10, Ubuntu
Posts: 9

Rep: Reputation: 0
read multiple input with bash


Hi,

As I'm starting to learn bash scripting I'm trying to automatize some tasks I usually perform. I have a notification mail I need to send several times a day. It has this structure:


Quote:
Dear user,

blah blah blah blah

You need to contact the following people:

user@example.com
user2@example.net
user3@example.org
and so on..

blah blah blah

Regards

To replace "user", I found this:

Code:
read -p "Please enter username: " username
echo "Dear $username,"
Which probe to be very useful with other simple notifications like this. But I don't know how to manage the email addresses as they are usually more than one and could vary from 1 to 10. They should appear one above the other.

I found this:

"Here is a little work around. The only thing the user needs to do is hit enter without anything else on a line and it will close out"
Code:
#!/usr/bin/ksh
word=a
until [[ $word = "" ]];do
read word?"Enter Word: "
bword=$bword"\n"$word
done
print $bword
here



I tried to use it and modify for my needs but I failed, I don't realize yet how can I use it.


If possible, I would like to use the until loop like the above example just for learning purposes but any other form will be accepted as well.


Any help will be much appreciated. Thanks in advance!

Chris
 
Old 05-07-2010, 05:45 PM   #2
DrLove73
Senior Member
 
Registered: Sep 2009
Location: Srbobran, Serbia
Distribution: CentOS 5.5 i386 & x86_64
Posts: 1,118
Blog Entries: 1

Rep: Reputation: 129Reputation: 129
This should do it:
Code:
#!/bin/bash
NextEmail="\n"
until [ "a$NextEmail" = "a" ];do
   echo "Enter next E-mail: "
   read NextEmail
   Emails=$Emails"\n"$NextEmail
done
echo -e $Emails
echo -e $Emails >> text.txt
If you use "echo -e $Emails" inside the loop with top and bottom line you can watch the progress before the next e-mail:
Code:
#!/bin/bash
NextEmail="anything"
Emails=""
until [ "a$NextEmail" = "a" ];do
   echo "Enter next E-mail: "
   read NextEmail
   if [ "a$Emails" = "a" ];then
      Emails=$NextEmail
   else
      if [ "a$NextEmail" = "a" ];then
         echo ""
      else
         Emails=$Emails"\n"$NextEmail
      fi
   fi
   echo "Current list:"
   echo "-------------------"
   echo -e $Emails
   echo "-------------------"
done
echo "Final list:"
echo "-------------------"
echo -e $Emails
echo "-------------------"

echo "" >> text.txt # Optional
echo -e $Emails >> text.txt
echo "" >> text.txt # Optional

Last edited by DrLove73; 05-07-2010 at 06:04 PM.
 
1 members found this post helpful.
Old 05-07-2010, 06:13 PM   #3
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
Look at using a HERE document for the body of the email. Use a variable for the recipients name inside the HERE document, which will be expanded when the document is produced. The info manual has a section on HERE documents.
Now you just need to read the name and email address in a loop and pipe the email to a program such as `nail' to send it.
 
1 members found this post helpful.
Old 05-08-2010, 12:16 AM   #4
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Assuming you use a selection from a pool of email addresses this allows you to interactively pick them from a list
Code:
#!/bin/bash

read -p "Please enter username: " username
text="Dear $username,"$'\n'$'\n'$'\n'

addresses=( $( cat addresses.txt ) )
select address in ${addresses[*]} Quit
do
    [[ $REPLY -gt ${#addresses[*]} ]] && break
    address=${addresses[REPLY-1]}
    text="$text$address"$'\n'
    echo "Added $address"
done

echo "$text" > message.txt
vi message.txt
 
1 members found this post helpful.
Old 05-08-2010, 01:12 AM   #5
DrLove73
Senior Member
 
Registered: Sep 2009
Location: Srbobran, Serbia
Distribution: CentOS 5.5 i386 & x86_64
Posts: 1,118
Blog Entries: 1

Rep: Reputation: 129Reputation: 129
@catkin's example can be further enhanced by using "dialog" package to create scrollable GUI menu.
 
1 members found this post helpful.
Old 05-08-2010, 04:46 PM   #6
zulsolar
LQ Newbie
 
Registered: Mar 2005
Location: Buenos Aires, Argentina
Distribution: Slackware, Solaris 10, Ubuntu
Posts: 9

Original Poster
Rep: Reputation: 0
Question

Hi guys,

First I wanna thank you for your help. And very quick indeed! As I'm just starting with bash scripting I must recognize that your solutions are far far away of my little knowledge yet, so it will take me some time to a full understanding of every line of the code you shared with me.

Anyway, I tested your examples and they worked great. That was what I were looking for.

Now I have a couple of questions. In DrLove73's code I have to add email addresses one by one and when script is executed they appear as a list, which is OK but I wonder if there is a way to paste all addresses needed at once, separated by a field separator (space for example) with same results, I mean, make them appear as a list. I'll give you an example to be more graphical:

In this example, I put one mail after another:

Code:
[chris@agena ~/bin]$ mails2
Enter next E-mail:
user@domain.tld
Enter next E-mail:
user2@domain.tld
Enter next E-mail:
user3@domain.tld
Enter next E-mail:


user@domain.tld
user2@domain.tld
user3@domain.tld

And it gives me list which is ok, as I told you. But when I tried to add all addresses at once, they not appear as a list, like this:

Code:
[chris@agena ~/bin]$ mails2
Enter next E-mail:
user@domain.tld user2@domain.tld user3@domain.tld
Enter next E-mail:


user@domain.tld user2@domain.tld user3@domain.tld

Is there a way to add all mails at once and make them appear as a list? I tried modifying your code but still no luck.


Another question I have is about the "/n". What does it mean? What does it do? On catkin's example, on line # 4, there are plenty of them:

Quote:
text="Dear $username,"$'\n'$'\n'$'\n'
Why so many of them? Are them part of echo command? Seems that they are referring a field separator but not sure of that.


Again, thank you very much for your help and for sharing your code. And sorry for my noob questions.

Chris
 
Old 05-08-2010, 04:56 PM   #7
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
In many programs and languages, \n means "newline".

And to split a space-separated list of words:

Code:
$ echo 'this is test text
> even more text' | awk '{ i=1; while(i<=NF) { print $i; i++; } }'
this
is
test
text
even
more
text

Last edited by MTK358; 05-08-2010 at 04:58 PM.
 
Old 05-08-2010, 06:31 PM   #8
DrLove73
Senior Member
 
Registered: Sep 2009
Location: Srbobran, Serbia
Distribution: CentOS 5.5 i386 & x86_64
Posts: 1,118
Blog Entries: 1

Rep: Reputation: 129Reputation: 129
To apply MTK358 solution into my scripts:
Code:
#!/bin/bash
NextEmail="\n"
until [ "a$NextEmail" = "a" ];do
   echo "Enter next E-mail: "
   read NextEmail
   for s in $(echo $NextEmail | awk '{ i=1; while(i<=NF) { print $i; i++; } }' | tr " " "\n" )
   do
      Emails=$Emails"\n"$s
   done
done
echo -e $Emails
echo -e $Emails >> text.txt
Code:
#!/bin/bash
NextEmail="anything"
Emails=""
until [ "a$NextEmail" = "a" ];do
   echo "Enter next E-mail: "
   read NextEmail
   if [ "a$Emails" = "a" ];then
      Emails=$NextEmail
   else
      if [ "a$NextEmail" = "a" ];then
         echo ""
      else
          for s in $(echo $NextEmail | awk '{ i=1; while(i<=NF) { print $i; i++; } }' | tr " " "\n" )
         do
            Emails=$Emails"\n"$s
         done
      fi
   fi
   echo "Current list:"
   echo "-------------------"
   echo -e $Emails
   echo "-------------------"
done
echo "Final list:"
echo "-------------------"
echo -e $Emails
echo "-------------------"

echo "" >> text.txt # Optional
echo -e $Emails >> text.txt
echo "" >> text.txt # Optional
And do not worry about learning, only year ago I started with serious bash programing. Using only online examples I mastered even loading multi-dimensional arrays from coma separated file, something that only has few examples online. If you are dedicated learner, you will soon master it.

Last edited by DrLove73; 05-09-2010 at 04:16 AM. Reason: removed qoutes
 
Old 05-08-2010, 07:08 PM   #9
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
AWK has the concepts of "records" (separated by newlines by default) and "fields" (separated by spaces by default).

So my script initializes variable i to 1, and the while loop increments i until it is greater than the built-in variable "NF", which is the number of fields in the current record.

And $(numerical value) gets the specified field from the current record, or the whole record for 0.
 
Old 05-09-2010, 02:20 AM   #10
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by zulsolar View Post
Why so many of them? Are them part of echo command? Seems that they are referring a field separator but not sure of that.
As already said "\n" (not "/n") means newline in many languages. The first may have been C. Here it is used in bash ANSI-C Quoting and is effectively a string consisting of a single newline. Why so many? I figured you might like to have some space for "blah blah blah" and I didn't think of using the saner $'\n\n\n'
 
Old 05-09-2010, 02:22 AM   #11
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by zulsolar View Post
As I'm just starting with bash scripting I must recognize that your solutions are far far away of my little knowledge yet, so it will take me some time to a full understanding of every line of the code you shared with me.
If any of them are particularly puzzling please ask.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
read multiple lines from user input in c archanac07 Linux - Software 1 02-26-2010 05:15 AM
shell script having multiple grep statements-I want input file to be read only once mukta9003 Linux - Newbie 4 08-27-2008 12:58 AM
bash: read multiple lines in a file 300zxkyle Programming 7 07-29-2007 04:38 AM
Bash: How to read tab character when reading input new_to_bash Programming 7 12-09-2006 07:31 PM
verifing input from bash read michael_util Programming 1 01-13-2005 09:09 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:32 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration