Question: Can someone help me write a simple bash script that handles the following usage:

```
./application channels;message

eg:  ./application channel1 channel2 channel3;this is a message

```

so basically anything before the delimiter ; is channels separated by a space, and anything after the ; is the message.

Basically, i wanted to store each of these into a variale and print them out...

Answer: 
You probably want to look for a other way to delimit the message, since a semicolon will result that bash will read up to the semicolon and "think hey this is the end of the command". Then bash will run you program with the arguments before the semicolon. Subsequently it will look for a program or build-in called 'this' and provide 'is', 'a' and 'message' as command line arguments to this. However bash will probably answer with 'this: command not found'.
For more information look up the meaning of the ';'/semicolon operator in the [bash manual](http://www.gnu.org/software/bash/manual).

what you might do is something like the following

```
#!/bin/bash

message=""
outfiles=""

# Loop until all parameters are used up
# shift "eats" one argument at a time
# util there are no arguments left then $1 is a emtpy string
while [ "$1" != "" ]; do

    if [ "$1" == "-m" ] # the message
    then
        shift #"eat one arugment then $1 is your message"
        #you should check if there is a argument after "-m"
        message=$1
    else
        outfiles="$outfiles $1"
    fi

    # Shift all the parameters down by one
    shift

done

# put the message it the other arguments specified.

for i in $outfiles; do
    echo $message > $i
done

```

what this program does is checks for "-m" then it will shift all argument so you have arguments minus once and write this message to the oter arguments eg
$./program.bash -m "Hello world" output1.txt ouput2.txt
this program put message "Hello world" into newly created or (be carefull) overwritten files output1.txt output2.txt
```
while getopts m: opt
do
     case "$opt" in
     (m) message="$OPTARG";;
     (*) echo "Usage: $0 [-m 'message'] [chan ...]" >&2; exit 1;;
     esac
done
shift $(($OPTIND-1))

for channel in "$@"
do
    whatever -y because -m "$message" $channel
done

```

That should work. It leaves the message optional, and doesn't require you to specify any channels. You can add more options fairly easily (those that take an argument specified with a colon after the letter; those that don't take an argument without a colon). You can insist that `$#` is greater than 0 between the two loops (but the usage message has to change to reflect that). You can insist that a message is passed (but the usage message has to be changed for that, too). And so it goes on; your options are legion.

---

As noted in comments:

> 
> Note that `;` is a command delimiter to the shell. You will have to write:
> 
> 
> `./application 'channels;message'`
> 
> 
> with quotes around the semicolon or a backslash before it. That's a not very orthodox usage; you might use a more idiomatic notation such as:
> 
> 
> `./application -m "this is a message" channel1 channel2 channel3`
> 
> 
> 

The script above implements this suggestion fairly accurately.

> 
> The only problem I see, is what if the message has `"` characters in it. `./application -m "this isn"t a message" channel1` etc...
> 
> 
> 

You need to be cognizant of shell metacharacters, which include `"'`$;(`. For all those, you'll need to escape the culprit character:

```
./application -m 'He said, "Don'\''t do that!"' chan1

```

Generally, use single quotes around a message; where you have a single quote to write, type `'\''` instead.

```
./application -m 'He said, "This is a message."' chan1
./application -m "This isn't a message." chan2
./application -m 'He said, "This isn'\''t a message", but they disagreed." chan3

```