1
00:00:03,100 --> 00:00:06,470
In this lesson you'll learn how to use the case statement.

2
00:00:06,610 --> 00:00:12,790
The case statement is the perfect way to make a decision based on the value of a given variable.

3
00:00:12,790 --> 00:00:17,620
This is especially true when you have a specific set of values that you're looking for.

4
00:00:17,620 --> 00:00:23,800
So first off I'm going to open up a terminal on my local machine and then go into our class a folder

5
00:00:23,800 --> 00:00:32,730
of shell class and from there I'm going to go into the local user's directory and now I'm going to start

6
00:00:32,730 --> 00:00:39,260
the virtual machine with vagrant up.

7
00:00:39,400 --> 00:00:45,980
Now that the machine is booted we'll connect with vagrant S-sh and from here we can move into our shared

8
00:00:46,040 --> 00:00:49,210
folder of Ford slash vagrant.

9
00:00:49,490 --> 00:00:55,220
So far in this course you've been using the if statement to perform tests and to make decisions in your

10
00:00:55,220 --> 00:01:00,680
scripts today you're going to learn how to make decisions using the case statement.

11
00:01:00,680 --> 00:01:04,930
Now before we start writing our script let's look at the case command itself.

12
00:01:05,060 --> 00:01:06,660
First off it's a shell built in.

13
00:01:06,670 --> 00:01:12,830
And we know this because we can type the type command type Dasch A and specify the command which is

14
00:01:12,830 --> 00:01:18,230
case and his case is a shell keyword which is a type of shell built in.

15
00:01:18,260 --> 00:01:22,920
Of course since it's a shell built in you know that we can get some information on how to use it with

16
00:01:22,920 --> 00:01:26,280
the help built and so will run help case.

17
00:01:26,480 --> 00:01:30,010
The first line shows us the syntax of how to use the case statement.

18
00:01:30,140 --> 00:01:35,540
It's all squeezed together on one line so it's a bit hard to read and I'm going to flush it out for

19
00:01:35,540 --> 00:01:40,010
you in this script I'm about to write so you can see the syntax very clearly.

20
00:01:40,010 --> 00:01:46,340
Also this output tells us that commands will be executed based on pattern matching.

21
00:01:46,340 --> 00:01:51,950
So what you do with the case statement is compare a value to a pattern and if the value matches that

22
00:01:51,950 --> 00:01:58,550
pattern the commands associated with that pattern or below that pattern get executed if the pattern

23
00:01:58,640 --> 00:01:59,730
isn't matched.

24
00:01:59,750 --> 00:02:01,570
Nothing gets executed.

25
00:02:01,700 --> 00:02:05,600
Again this will become pretty obvious with a couple of simple examples.

26
00:02:05,600 --> 00:02:10,000
So I'm going to name this script l user Dymo 0 9

27
00:02:14,410 --> 00:02:14,930
will start.

28
00:02:14,960 --> 00:02:17,220
All scripts like we do with the shebang.

29
00:02:17,600 --> 00:02:21,780
And then let's add a comment here about what this script is going to do.

30
00:02:27,780 --> 00:02:33,440
Let's start with something you already know which is the if statement by the way using the if statement

31
00:02:33,450 --> 00:02:38,700
in the way we're about to use it is not really the ideal way to handle the situation.

32
00:02:38,820 --> 00:02:44,500
But the reason I'm going to show you this is because one it builds upon what you already know too.

33
00:02:44,520 --> 00:02:49,170
You're going to see it done this way and other scripts so it's best to know what is going on when you

34
00:02:49,170 --> 00:02:50,020
see that.

35
00:02:50,100 --> 00:02:56,550
And 3 it serves as a nice comparison for the better way to handle this situation which is to use a case

36
00:02:56,550 --> 00:02:59,580
statement which of course will be getting to soon enough.

37
00:02:59,610 --> 00:03:05,550
So with that little disclaimer out of the way let's say you want to do something if the word start was

38
00:03:05,550 --> 00:03:12,060
passed in as the first argument to your shellscript you know that the first argument is stored in dollar

39
00:03:12,060 --> 00:03:12,950
sign one.

40
00:03:13,050 --> 00:03:16,120
So you can do something like this if

41
00:03:19,770 --> 00:03:28,570
dollar sign one is equal to start then let's say we just want to echo the word starting then we close

42
00:03:28,570 --> 00:03:36,610
out our IF statement and with F I that's right and quit or changes here make the script executable

43
00:03:41,160 --> 00:03:42,540
and then test it out.

44
00:03:46,960 --> 00:03:48,040
So that looks like it works.

45
00:03:48,040 --> 00:03:53,490
So if we supply anything other than start as the first argument nothing happens in our script.

46
00:03:53,500 --> 00:03:54,940
Let's go ahead and try that out.

47
00:03:54,940 --> 00:03:57,140
We'll try this nothing happens.

48
00:03:57,160 --> 00:03:59,150
We'll try this nothing happens.

49
00:03:59,170 --> 00:04:05,320
Of course if we don't supply anything then nothing happens so again that is working as we expect it

50
00:04:05,320 --> 00:04:05,870
to.

51
00:04:06,190 --> 00:04:09,850
If we want to account for other cases we need to code for it.

52
00:04:09,850 --> 00:04:16,330
So let's take a quick look at the help for the IF command will do help if what we need to use to build

53
00:04:16,330 --> 00:04:22,030
out our IF statement to account for other strings is Elif which is short for else.

54
00:04:22,120 --> 00:04:29,750
If so let's get back into our script and account for stop as an argument.

55
00:04:29,920 --> 00:04:32,840
I'm going to go up here and add Elif

56
00:04:36,560 --> 00:04:46,620
of dollars on one is equal to stop then we'll echo stopping if read our code from the top down.

57
00:04:46,630 --> 00:04:52,370
If dollar sign one equal start then what we're going to do is echo starting else.

58
00:04:52,480 --> 00:04:58,060
If dollar sign one equal stop then what we'll do is echo stopping it's pretty pretty intuitive the way

59
00:04:58,060 --> 00:04:59,230
this is working out.

60
00:04:59,230 --> 00:05:01,690
So let's say for changes and try it out.

61
00:05:05,100 --> 00:05:09,480
Sure enough we pass and stop and stopping it's displayed to the screen.

62
00:05:09,480 --> 00:05:13,970
So let's go ahead jump back in and add another left to handle status.

63
00:05:15,260 --> 00:05:16,000
So here we'll go.

64
00:05:16,010 --> 00:05:16,520
Elif

65
00:05:19,380 --> 00:05:32,180
Alasan one is equal to status then will echo status while we're here let's handle all other cases within

66
00:05:32,260 --> 00:05:32,970
else.

67
00:05:32,990 --> 00:05:39,380
Let's also make this an error message by sending the output to standard error and exit with a non zero

68
00:05:39,410 --> 00:05:40,600
exit status.

69
00:05:51,520 --> 00:05:53,070
OK let's try this out.

70
00:05:53,880 --> 00:06:01,880
So we'll do a user test demo nind at SC status display status to our screen which is what we want.

71
00:06:01,920 --> 00:06:03,910
Let's pass this and restart.

72
00:06:04,050 --> 00:06:06,810
And it says hey restart is not a valid option.

73
00:06:06,810 --> 00:06:08,880
Please supply a valid option.

74
00:06:09,030 --> 00:06:12,790
And so we can check our exit status here and sure enough it's one.

75
00:06:12,810 --> 00:06:18,870
And of course if we don't display or pass anything into our script we also get the same situation we

76
00:06:18,870 --> 00:06:25,150
need to supply a valid option so that our script is doing is taking an action based on the value stored

77
00:06:25,180 --> 00:06:27,730
and dollar sign one in our script.

78
00:06:27,730 --> 00:06:31,170
Now if you stopped right here that would be absolutely fine.

79
00:06:31,180 --> 00:06:35,920
You made things work with the tools and skills that you had at the moment which is what we all do anyway

80
00:06:35,920 --> 00:06:36,350
right.

81
00:06:36,520 --> 00:06:44,900
But let's add to your skills and recreate this exact same functionality using a case statement.

82
00:06:44,930 --> 00:06:50,510
Let me go ahead and comment out all that existing code first and then we'll go ahead and build on it

83
00:06:50,510 --> 00:06:51,380
from here.

84
00:06:58,680 --> 00:07:00,980
Now let's build out our case statement.

85
00:07:01,080 --> 00:07:07,180
The first line consists of the word case followed by the value that you are going to check.

86
00:07:07,200 --> 00:07:11,230
In our case that value is stored in side dollar sign one.

87
00:07:11,280 --> 00:07:14,800
And finally we're going to end the line with the word end.

88
00:07:14,850 --> 00:07:21,930
So we have case our variable and in case dollar sign one in next what we need to do is supply a pattern

89
00:07:22,200 --> 00:07:24,670
followed by a closing parenthesis.

90
00:07:24,690 --> 00:07:29,310
For example we want to see if dollar sign one matches the word start.

91
00:07:29,370 --> 00:07:30,780
So we do this

92
00:07:34,070 --> 00:07:39,590
this means if dollar sign one is equal to start then execute the code that follows.

93
00:07:39,600 --> 00:07:41,910
And here's the code that we want to execute.

94
00:07:46,470 --> 00:07:52,170
If you wanted to execute many commands you would simply supply them on a separate line to end the code

95
00:07:52,180 --> 00:07:57,740
block use to semi-colons to finish the case statement.

96
00:07:57,740 --> 00:08:01,490
Spell the word case backwards.

97
00:08:01,500 --> 00:08:01,750
All right.

98
00:08:01,770 --> 00:08:03,320
So let's try this out.

99
00:08:08,150 --> 00:08:08,900
So that works.

100
00:08:08,900 --> 00:08:10,230
Now let's go ahead.

101
00:08:10,340 --> 00:08:14,690
Go back and add the other patterns that we're looking for to our case statement.

102
00:08:19,320 --> 00:08:25,560
So now we're looking for the word stop and then what we're going to do there is Echo stopping to the

103
00:08:25,560 --> 00:08:30,340
screen and in our code block with a two semi-colons.

104
00:08:30,540 --> 00:08:32,700
And let's also look for status

105
00:08:42,510 --> 00:08:48,740
so notice how we're not repeating ourselves multiple times like we did with the if statement we supply

106
00:08:48,740 --> 00:08:54,340
the value that we're checking once and then all patterns we're looking to match.

107
00:08:54,350 --> 00:08:59,750
So if we go back up in our script we use if dollar sign one is this LFA dollars on one is that a dollar

108
00:08:59,750 --> 00:09:01,700
sign one is something else and so on.

109
00:09:01,880 --> 00:09:07,040
But here in our case statement we say if dollar sign one is this that or the other then we're going

110
00:09:07,040 --> 00:09:08,810
to do something based on that value.

111
00:09:08,810 --> 00:09:14,980
Again it's much cleaner in my opinion than the longer if statement that we see above.

112
00:09:15,410 --> 00:09:17,870
So let's make sure that this little bit of code works

113
00:09:22,430 --> 00:09:27,820
a stopping argument works let's look at the status argument and that works as well.

114
00:09:27,820 --> 00:09:33,700
The only thing that is left to account for is anything that does not match the strings start stop and

115
00:09:33,700 --> 00:09:34,690
status.

116
00:09:34,690 --> 00:09:41,670
So let's quickly reference the bash man page and get some more information on patterns as they are used

117
00:09:41,680 --> 00:09:42,770
with the case statement.

118
00:09:42,770 --> 00:09:54,970
So I'm going to type in man bash and I'm on a search for the case statement here SCO case.

119
00:09:55,010 --> 00:09:56,050
Here we go.

120
00:09:56,180 --> 00:10:03,830
It reads a case command first expands word and tries to match it against each pattern in turn using

121
00:10:03,830 --> 00:10:07,960
the same matching rules as for pathname expansion.

122
00:10:08,030 --> 00:10:11,560
And then it tells us to see pathname expansion below.

123
00:10:11,780 --> 00:10:25,180
So that means we have to look at that section of the man page and we do that now pathname Stu XP.

124
00:10:25,240 --> 00:10:29,920
Here we are really what we're looking for in this section is about pattern matching.

125
00:10:29,920 --> 00:10:34,780
So let me just page down here until we get it there it is pattern matching.

126
00:10:34,780 --> 00:10:41,500
So let's see here it says any character that appears in a pattern other than the special pattern characters

127
00:10:41,500 --> 00:10:44,190
described below matches itself.

128
00:10:44,380 --> 00:10:47,580
That's the type of pattern we have been using so far.

129
00:10:47,620 --> 00:10:56,290
For example our first pattern in our case statement is S T A R T which only matches that exact sequence

130
00:10:56,290 --> 00:11:02,510
of characters the special characters here are asterisk questionmark and brackets.

131
00:11:02,620 --> 00:11:06,520
The asterisk matches any string including the null string said.

132
00:11:06,670 --> 00:11:09,870
Another way asterisk matches anything.

133
00:11:10,060 --> 00:11:12,100
I'm sure you've probably used this before right.

134
00:11:12,100 --> 00:11:20,110
So for example if you want to get a list of files that end in s t you would run LS space asterisk t

135
00:11:20,110 --> 00:11:21,270
s t.

136
00:11:21,280 --> 00:11:23,250
Now we can do the exact same thing.

137
00:11:23,260 --> 00:11:25,510
In our case statements.

138
00:11:25,510 --> 00:11:29,510
Now the question mark matches any single character.

139
00:11:29,530 --> 00:11:34,960
Finally the brackets are used to match any characters contained within those brackets and you can also

140
00:11:34,960 --> 00:11:39,880
specify a range of characters by separating them with a hyphen.

141
00:11:39,880 --> 00:11:44,060
This is all good information to know how to use questionmark in the brackets and all that.

142
00:11:44,170 --> 00:11:50,020
But for our purposes right now we only need the asterisk for our current use case because we just want

143
00:11:50,020 --> 00:11:53,790
to match anything else that wasn't already specified.

144
00:11:53,830 --> 00:11:55,790
So we'll get on the main page with typing Q.

145
00:11:55,870 --> 00:11:59,920
We'll get back to our script by starting our editor again.

146
00:11:59,920 --> 00:12:05,320
So now let's match anything that is not already specified by using asterisks as our pattern.

147
00:12:05,320 --> 00:12:08,240
So we'll do this matches anything.

148
00:12:09,450 --> 00:12:13,230
And then we'll say supply a valid option.

149
00:12:14,210 --> 00:12:16,210
Send that to standard air.

150
00:12:16,430 --> 00:12:21,260
Exit our script with the non-zero exit status obviously 1 is not zero so that's going to work for us

151
00:12:21,920 --> 00:12:29,050
and then we'll close out our statement here with semi colons.

152
00:12:29,130 --> 00:12:32,910
Remember that your scripts are being executed from the top down.

153
00:12:32,910 --> 00:12:38,880
So once a match is found the associated code block gets executed if you want to make sure something

154
00:12:38,880 --> 00:12:42,270
matches Furse will then put it first in your list.

155
00:12:42,270 --> 00:12:48,570
In this case we're doing the opposite and using the asterisk as a catchall to match anything that hasn't

156
00:12:48,570 --> 00:12:53,780
already been accounted for and we're putting that last and our list of patterns.

157
00:12:53,820 --> 00:12:59,870
So let's go ahead and try out our code we'll do Ellies user demo 0 9 start.

158
00:12:59,870 --> 00:13:02,640
That works let's try stop.

159
00:13:02,850 --> 00:13:07,130
Whoops I accidentally ended the line with a line continuation character but this is going to work anyway

160
00:13:07,130 --> 00:13:12,140
I'll just hit enter and sure enough that works let me take that off and hit enter and that's what it

161
00:13:12,140 --> 00:13:14,870
should really look like Excuse my typing mistake there.

162
00:13:14,930 --> 00:13:16,090
Anyway let's keep trying.

163
00:13:16,100 --> 00:13:22,090
Are other options here we want to make sure that status gets matched it does it reports back status.

164
00:13:22,100 --> 00:13:23,300
Will do restart.

165
00:13:23,320 --> 00:13:29,740
For example here when we pass and restarted says supply a valid option because it does not match.

166
00:13:29,750 --> 00:13:35,520
Start stop status but it does match the asterisk and executes that code.

167
00:13:36,330 --> 00:13:42,240
Let's say we want to modify the script a bit and allow a user to provide the word status or state and

168
00:13:42,240 --> 00:13:44,660
still execute the same code.

169
00:13:44,880 --> 00:13:51,510
So let's look at help case and I glossed over this earlier but in the help output here for the case

170
00:13:51,510 --> 00:13:56,700
statement it says that you can use a pipe to separate multiple patterns.

171
00:13:56,910 --> 00:14:03,160
So I'll go back here and then we'll change status here to status pipe.

172
00:14:03,240 --> 00:14:05,000
What you can think of as an OR.

173
00:14:05,130 --> 00:14:08,750
And then we'll type in the word state that we want to match.

174
00:14:08,790 --> 00:14:16,740
Now if dollar sign one equals a status or it equal state the code echo status will be executed by the

175
00:14:16,740 --> 00:14:23,550
way instead of using two pattern separated by a pipe symbol we could have used as th asterisk as the

176
00:14:23,550 --> 00:14:24,390
Panner.

177
00:14:24,430 --> 00:14:27,810
Now that would match the words status and state.

178
00:14:27,810 --> 00:14:36,060
However it's not as exact because it would match other things like statu stateless static and many others.

179
00:14:36,060 --> 00:14:40,570
I just wanted to share another way you could approach this but I like them more exacting option.

180
00:14:40,580 --> 00:14:43,590
We went with here so let's try it out.

181
00:14:43,750 --> 00:14:48,770
So will do l user Dymo 9 state and that reports a status.

182
00:14:48,870 --> 00:14:57,510
And of course we can do status here as well and that works just so you know you can use multiple pipes

183
00:14:57,510 --> 00:14:58,460
in your pattern.

184
00:14:58,560 --> 00:15:06,930
So let's expand our script to accept dash dash status and dash dash state so we can do this dashed status

185
00:15:07,050 --> 00:15:13,360
or dash dash state save our changes and try our code.

186
00:15:13,440 --> 00:15:20,640
So do dash dash state first and that works dash dash status that works and if we supply something that

187
00:15:20,640 --> 00:15:28,590
doesn't match like this then we fall back into the asterisk pattern and get that code block there.

188
00:15:28,620 --> 00:15:33,690
Let's wrap up this lesson by talking about spacing and style

189
00:15:36,920 --> 00:15:42,410
just so you know a case statement like this is really the basis of most init scripts.

190
00:15:42,410 --> 00:15:50,990
For example on older Linux distributions you would run ETSI a net the S-sh D status and you would be

191
00:15:50,990 --> 00:15:54,650
provided with the status of the S-sh d service.

192
00:15:54,650 --> 00:16:02,270
Likewise you would stop the service by executing at CNET daddy s s h d stop and so on and so forth just

193
00:16:02,270 --> 00:16:08,600
kind of like we have laid out here all the systems services were handled by a simple shell script that

194
00:16:08,600 --> 00:16:10,460
used a case statement.

195
00:16:10,460 --> 00:16:16,940
Anyway let's quickly talk about spacing what I chose to do when creating my case statement was to indent

196
00:16:17,000 --> 00:16:19,490
each section by two spaces.

197
00:16:19,520 --> 00:16:24,050
For example the patterns were indented two spaces from the beginning of the case statement.

198
00:16:24,050 --> 00:16:28,820
Likewise the commands underneath each pattern were also indented two spaces from the beginning of the

199
00:16:28,820 --> 00:16:29,550
pattern.

200
00:16:29,810 --> 00:16:35,000
If you are for spaces type of person you can do that if you like using tabs instead of spaces.

201
00:16:35,000 --> 00:16:36,950
That would be fine as well.

202
00:16:36,980 --> 00:16:43,210
You can even forego the spaces altogether and have everything at the same level of indentation.

203
00:16:43,340 --> 00:16:48,830
But in my opinion it's harder to read a case statement or an if statement or really anything else without

204
00:16:48,860 --> 00:16:52,760
indentation so I don't recommend that approach.

205
00:16:52,760 --> 00:16:58,400
If you're only executing one command following a pattern it's a common practice to keep that command

206
00:16:58,400 --> 00:17:04,430
on the same line as the pattern match and to also include the closing double semi-colons on that same

207
00:17:04,430 --> 00:17:05,600
line as well.

208
00:17:05,600 --> 00:17:10,610
Let me create a copy of the case statement to manipulate and I'll clean it out as well.

209
00:17:10,640 --> 00:17:11,240
So just

210
00:17:14,820 --> 00:17:18,940
copy that below and then I'll go ahead and comment it out.

211
00:17:22,390 --> 00:17:31,560
There we go while I'm here I'm going to clean up that status pattern so I'll just do this.

212
00:17:31,890 --> 00:17:34,430
So let me go ahead and put these lines together here.

213
00:17:39,440 --> 00:17:44,800
Notice that I'm leaving a space after the parentheses and before the semi-colon.

214
00:17:44,900 --> 00:17:50,320
That's not technically required by syntax but it's a little bit cleaner in my opinion.

215
00:17:50,360 --> 00:17:55,670
Now I'm not going to change the code block for our catch all pattern which includes the asterisk pattern.

216
00:17:55,790 --> 00:18:01,850
It's multiple commands and it could get confusing running all those commands together plus by the way

217
00:18:01,850 --> 00:18:07,610
we haven't talked about the command separator you have to use if you want to execute multiple commands

218
00:18:07,610 --> 00:18:10,150
on a single line and we'll be getting to that later.

219
00:18:10,990 --> 00:18:16,220
Now if you look at this case statement it's a fairly compact yet it's pretty clear.

220
00:18:16,230 --> 00:18:22,630
It's pretty easy to read down the list of pattern start stop status and then the asterisk for everything

221
00:18:22,630 --> 00:18:23,230
else.

222
00:18:23,260 --> 00:18:27,190
So let's make sure that this newly formatted case statement still works.

223
00:18:31,730 --> 00:18:33,610
OK it still works with start.

224
00:18:33,610 --> 00:18:35,560
Does it work with Stop it does.

225
00:18:35,560 --> 00:18:41,500
Let's give it nothing which should match the asterisk pattern and sure enough it tells us to supply

226
00:18:41,500 --> 00:18:48,730
a valid option so that still works even though we formatted it slightly differently before we wrap things

227
00:18:48,730 --> 00:18:48,900
up.

228
00:18:48,900 --> 00:18:53,980
I wanted to point out that you can use the case statement in conjunction with values other than dollar

229
00:18:53,980 --> 00:18:55,180
sign 1.

230
00:18:55,240 --> 00:19:00,970
For example you could prompt the user for input and use a case statement to make a decision based on

231
00:19:00,970 --> 00:19:02,110
that input.

232
00:19:02,110 --> 00:19:05,070
You could create a simple menu system that way for example.

233
00:19:05,290 --> 00:19:11,750
Well that brings this lesson to a close in this lesson you learned how to use the case statement.

234
00:19:11,800 --> 00:19:17,590
If you find yourself writing a large if elif statement comparing different values against the exact

235
00:19:17,590 --> 00:19:18,660
same variable.

236
00:19:18,730 --> 00:19:22,040
Consider using a case statement in its place.

237
00:19:22,060 --> 00:19:26,810
You can check the contents of a variable against the list of patterns that you specify.

238
00:19:27,010 --> 00:19:31,480
You can do exact matches by specifying the exact string that you're looking for.

239
00:19:31,480 --> 00:19:37,570
You can also perform matches with patterns that include asterisk question marks and brackets to perform

240
00:19:37,570 --> 00:19:43,210
the same set of actions against multiple patterns separate each pattern with a pipe.

241
00:19:43,210 --> 00:19:49,630
Remember to end each pattern with a closing parenthesis and the code block for a given pattern executes

242
00:19:49,720 --> 00:19:52,720
until it encounters two semi-colons.
