forked from xianyunyh/PHP-Interview
-
Notifications
You must be signed in to change notification settings - Fork 0
/
shell.md
480 lines (323 loc) · 10.4 KB
/
shell.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
## shell入门教程
> Linux中的shell有多种类型,其中最常用的几种是Bourne shell(sh)、C shell(csh)和Korn shell(ksh)。三种shell各有优缺点。
> Bourne shell是UNIX最初使用的shell,并且在每种UNIX上都可以使用。Bourne shell在shell编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种shell。Linux操作系统缺省的shell是Bourne Again shell,它是Bourne shell的扩展,简称Bash,与Bourne shell完全向后兼容,并且在Bourne shell的基础上增加、增强了很多特性。Bash放在/bin/bash中,它有许多特色,可以提供如命令补全、命令编辑和命令历史表等功能,它还包含了很多C shell和Korn shell中的优点,有灵活和强大的编程接口,同时又有很友好的用户界面。
可以使用 `cat /etc/shells` 查看支持的shell类型。我们最常用的就是bash。兼容sh
- 头声明
shell脚本第一行必须以 #!开头,它表示该脚本使用后面的解释器解释执行。
```shell
#!/bin/bash
```
### shell变量
**shell变量中间不能有空格,合法的标识符(字母、数字、_),不能使用关键字。首字母必须是字母**
**变量赋值的时候,中间的等于号前后不能有空格**。
```shell
name=11
echo $name
1name //错误
_name //错误
name = "hello" //错误
```
2. 使用变量
定义过的变量直接使用$来访问这个变量
```shell
name="test"
echo $name
echo ${name}
```
3. 只读变量。
在一个变量的前面加上readonly 表示该变量只读。类似于常量。
```
readonly PI=3.14
echo $PI
```
4. 删除变量
当一个变量不再使用的时候,可以使用unset删除
```shell
name="test"
unset $name
```
变量的类型。有局部变量、环境变量、shell变量
### 字符串
字符串和php类似。可以由双引号和单引号括起来
但是双引号括起来的字符串,里面的变量可以解析。
单引号里面不能出现双引号(转义也不可以).所以尽量使用双引号
```shell
str="hello''"
str2='hello'
str3='"test"'//错误
str4="str2$str2"
echo $str4
```
- 字符串拼接
字符串拼接和其他的语言不一样。不需要.也不需要+
```shell
name1="hello"
name2="world"
echo $name1 $name2// hello world
```
- 获取字符串的长度
```shell
str="helloworld"
${#str}
```
- 字符串切片
使用冒号:
```
str="helloworld"
echo ${str:0:4} //从0开始截取4个字符 hell
```
- 字符串判断操作
```shell
${var} 变量var的值, 与$var相同
${var-DEFAULT} 如果var没有被声明, 那么就以$DEFAULT作为其值 *
${var:-DEFAULT} 如果var没有被声明, 或者其值为空, 那么就以$DEFAULT作为其值 *
${var=DEFAULT} 如果var没有被声明, 那么就以$DEFAULT作为其值 *
${var:=DEFAULT} 如果var没有被声明, 或者其值为空, 那么就以$DEFAULT作为其值 *
${var+OTHER} 如果var声明了, 那么其值就是$OTHER, 否则就为null字符串
${var:+OTHER} 如果var被设置了, 那么其值就是$OTHER, 否则就为null字符串
${var?ERR_MSG} 如果var没被声明, 那么就打印$ERR_MSG *
${var:?ERR_MSG} 如果var没被设置, 那么就打印$ERR_MSG *
${!varprefix*} 匹配之前所有以varprefix开头进行声明的变量
${!varprefix@} 匹配之前所有以varprefix开头进行声明的变量
```
- 字符串截取
```shell
${#string} $string的长度
${string:position} 在$string中, 从位置$position开始提取子串
${string:position:length} 在$string中, 从位置$position开始提取长度为$length的子串
${string#substring} 从变量$string的开头, 删除最短匹配$substring的子串
${string##substring} 从变量$string的开头, 删除最长匹配$substring的子串
${string%substring} 从变量$string的结尾, 删除最短匹配$substring的子串
${string%%substring} 从变量$string的结尾, 删除最长匹配$substring的子串
${string/substring/replacement} 使用$replacement, 来代替第一个匹配的$substring
${string//substring/replacement} 使用$replacement, 代替所有匹配的$substring
${string/#substring/replacement} 如果$string的前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
${string/%substring/replacement} 如果$string的后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
例子
str="hello"
echo ${#str}//5
echo ${str:0:2} //he
echo ${str/l/test}//heltesto
echo ${str//l/test} //hetesttesto
```
### 数组
shell数组支持一维数组。和php类似。不需要指定数组的大小。
数组用括号抱起来。每个元素用空格分割
arr=(a1 a2 a3)
```shell
arr=(1 2 3)
${arr[0]}//1
```
- 获取数组所有的元素
使用@ 或 * 可以获取数组中的所有元素
```shell
${arr[*]}
```
- 获取数组的长度
```shell
${#arr[*]}
```
- 遍历数组
```shell
for a in ${arr[*]};do
echo $a
done
```
- 数组第n个元素的长度
```shell
${#arr[2]}
```
- 数组切片
```shell
${arr[*]:0:2} //1 2
```
- 数组搜索替换
```shell
${arr[*]/3/5}
```
- 添加元素到数组
```shell
arr=("${arr[*]}" "test")
```
## 运算符
### 逻辑运算符
```shell
&& 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true
```
### 字符串比较
```shell
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否为0,不为0返回 true。 [ -n $a ] 返回 true。
str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。
```
### 关系运算符
关系运算符只支持数字
```shell
eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。
```
```shell
a=10
b=20
if [[ $a eq $b ]];then
echo "等于"
fi
```
### 布尔运算符
```shell
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。
```
### 文件测试符号
```shell
b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
-p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
-r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。
```
```shell
file=""
if [[-f $file ]]; then
echo "is a file"
fi
```
## 流程控制
### if/else
```shell
if [[condition]];then
echo '1'
fi
//if else
if [[condition]]; then
echo '1'
else
echo '2'
fi
# if elseif else
if [[condition]];then
elif [[condition]];then
fi
```
### for
```shell
for i in list1 list2 ;do
echo $i
done
for i in 1 2 3 4;do
echo $i
done
//1 2 3 4
for (( i = 0; i < 10; i++ )); do
echo $i
done
```
### while
```shell
while [[ condition ]]; do
#statements
done
```
**demo例子**
```shell
#! /bin/bash
a=10
b=20
# 判断数值
if [[ $a -ne $b ]]; then
echo "a 不等于b"
fi
# 判断字符串
if [[ '$a' != '$b' ]]; then
echo "1"
fi
# 判断文件
if [[ -d "../doc" ]]; then
echo "dirctory"
fi
if [[ ! -f "../routes" ]]; then
echo "not a file"
fi
#while
while [[ $a -gt 1 ]]; do
#statements
echo $a;
# 条件
let a--
done
# for
for i in "wo" "rds"; do
echo $i
done
```
## 函数
shell中的函数 定义如下
```shell
其中function是可以省略的
[function] functionName(){}
function test(){
}
test(){
}
```
- 函数的调用
函数的调用和其他语言的调用不太一样
```shell
function test()
{
echo "hello"
}
test #调用函数
```
- 函数的参数
函数的参数定义不需要在()中定义形参 只需要在调用使用传入即可
`$n n代表整数` $1是第一个参数 以此类推
```shell
function test()
{
echo $1 # 第一个参数 以此类推
}
test 22 //22
```
## 引入外部文件
在shell中有时候需要引入外部的脚本文件 我们需要使用下面的两种方式
1. . filename
```shell
. ./a.sh
```
2. source filename
在文件中使用source
```shell
source ./a.sh
```
## 命令行接收参数
在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。
```shell
$ bash test.sh test test2
$0 代表脚本文件 //test.sh
$1 代表第一个参数 //test
$# 参数的个数 // 2
$* 所有参数
for i in $*; do
echo $i
done
$$ 脚本运行的进程号
$! 最后一个进程号
$? 最后退出的状态 0 表示没有问题
```