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: 
Since you require one message and one or more channels, it makes more sense to specify the message first, then assume that the rest of the arguments are channels. Something like

```
#!/bin/bash

message="$1"
shift  # Now each argument in $@ is a channel

```

Then your script could be run as follows

```
$ ./application "This is a message" channel1 channel2 channel3

```

While this how you typically handle required arguments, one drawback compared to using `-m` to specify the message is that it's harder to tell if the user forgot to specify the message

```
# Is "channel1" the message, or did the user forget to specify one?
$ ./application channel1 channel2 channel3

```

For implementing `-m`, I refer you to [Jonathan Leffler's answer](https://stackoverflow.com/a/14946888/1126841).
```
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

```