文件的格式及执行
文件格式
文件第一行标识需要用什么语言执行脚本。文件以 .sh 结尾,如test.sh
#! /bin/bash
文件执行
修改执行权限后执行
#修改文件权限chmod +x test.sh
使用source执行
不用修改执行权限,直接执行。要保证在当前文件的绝对路径下
source ./test.sh
使用bash执行
bash执行文件,会开启个新的进程
bash ./test.sh
单引号 双引号 反引号
关于变量
#! /bin/bashurl="shenshuai89@qq.com"#单引号不会转化变量,把内容作为完整字符串输出website1='shell:${url}'#双引号可以把内部的变量进行转化#使用双引号包围变量,可以 使变量内的空白以及换行都能正确显示website2="shell:${url}"#单引号输出 shell:${url}echo $website1#双引号输出 shell:shenshuai89@qq.comecho $website2# 反引号内放的是linux命令,会把命令执行的结果作为字符串打印出来`linux命令`[root@VM-0-11-centos code]# params=`ls`[root@VM-0-11-centos code]# echo $paramsdockerDemo nodeapi
定义变量和取消变量
name="123"echo ${name}# 输出:123unset nameecho ${name}#
shell变量面试题
[root@VM-0-11-centos shell]# echo user1=`whoami` > who.sh[root@VM-0-11-centos shell]# echo $user1[root@VM-0-11-centos shell]# source who.sh[root@VM-0-11-centos shell]# echo $user1root[root@VM-0-11-centos shell]# shsh-4.2# echo $user1sh-4.2#
- 每次调用bash都会开启一个子shell,不保留当前shell变量。
- 调用source是在当前shell环境加载脚本,因此会保留变量
关于格式
```bash使用双引号包围变量,可以使变量内的空白以及换行都能正确显示
所有结果整行输出,不进行换行
echo $(ls -l)
结果会做格式化显示,有空格和换行
echo “$(ls -l)”
字符串可以由单引号' '包围,也可以由双引号" "包围,也可以不用引号。它们之间是有区别<br />三种形式的区别:<br />1) 由单引号' '包围的字符串:- 任何字符都会原样输出,在其中使用变量是无效的。- 字符串中不能出现单引号,即使对单引号进行转义也不行。<br />2) 由双引号" "包围的字符串:- 如果其中包含了某个变量,那么该变量会被解析(得到该变量的值),而不是原样输出。- 字符串中可以出现双引号,只要它被转义了就行。<br />3) 不被引号包围的字符串- 不被引号包围的字符串中出现变量时也会被解析,这一点和双引号" "包围的字符串一样。- 字符串中不能出现空格,否则空格后边的字符串会作为其他变量或者命令解析。```bash#!/bin/bashn=66str1=shenshuai89@qq.com$n str2="shell \"script\" $n"str3='中文网 $n'echo $str1echo $str2echo $str3#输出结果# shenshuai89@qq.com66# shell "script" 66# 中文网 $n
str1 中包含了$n,它被解析为变量 n 的引用。$n后边有空格,紧随空格的是 str2;Shell 将 str2 解释为一个新的变量名,而不是作为字符串 str1 的一部分。
str2 中包含了引号,但是被转义了(由反斜杠\开头的表示转义字符)。str2 中也包含了$n,它也被解析为变量 n 的引用。
str3 中也包含了$n,但是仅仅是作为普通字符,并没有解析为变量 n 的引用。
特殊符号
| $$ | 当前 Shell 进程 PID |
|---|---|
| $0 | 当前脚本的绝对路径+文件名 |
| $1 | 第一个参数 |
| $2 | 第二个参数 |
| $# | 传递给脚本或函数的参数个数。 |
| $@ | 传递给脚本或函数的所有参数。 |
| $* | 传递给脚本或函数的所有参数。 |
| $? | 表示上一个命令的退出状态,或者上一个函数的返回值 |
function get() {echo "Process ID: $$"echo "File Name: $0"echo "First Parameter : $1"echo "Second Parameter : $2"echo "All parameters 1: $@"echo "All parameters 2: $*"echo "Total: $#"}get js shell
$?上个命令的退出状态
if [ "$1" == 100 ]thenexit 0elseexit 1fi
需要使用bash开启新进程测试,否则会退出
#测试bash ./return.shecho $?# 输出1bash ./return.sh 100echo $?# 输出1
$?函数的返回值
function add() {return $(($1+$2))}add 11 24echo $?
字符串
子串操作
mingyan=goodgoodstudy,daydayup!${变量} 返回变量值${#变量} 返回变量长度${变量:start} 返回变量start数值之后的字符,且包含start位置的字符${变量:start:length} 提取start之后的 [length长度]的字符,${变量#word} 从变量开头删除最短匹配的word子串 ${mingyan:good}${变量##word} 从变量开头删除最长匹配的word子串${变量%word} 从变量结尾删除最短的word${变量%%word} 从变量结尾开始删除最长匹配的word#替换操作${变量/pattern/string} 用string代替第一个匹配的pattern${变量//pattern/string} 用string代替所有的pattern
mingyan="goodgoodstudy,daydayup!"shuai@shuais-MacBook-Pro batchRename % echo ${mingyan}goodgoodstudy,daydayup!shuai@shuais-MacBook-Pro batchRename % echo ${#mingyan}23shuai@shuais-MacBook-Pro batchRename % echo ${mingyan:4}goodstudy,daydayup!shuai@shuais-MacBook-Pro batchRename % echo ${mingyan:4:9}goodstudyshuai@shuais-MacBook-Pro batchRename % echo ${mingyan#good}goodstudy,daydayup!shuai@shuais-MacBook-Pro batchRename % echo ${mingyan##good}goodstudy,daydayup!shuai@shuais-MacBook-Pro batchRename % echo ${mingyan##study}goodgoodstudy,daydayup!shuai@shuais-MacBook-Pro batchRename % echo ${mingyan##goodgoodstudy},daydayup!shuai@shuais-MacBook-Pro batchRename % echo ${mingyan%up!}goodgoodstudy,daydayshuai@shuais-MacBook-Pro batchRename % echo ${mingyan/good/hao}haogoodstudy,daydayup!shuai@shuais-MacBook-Pro batchRename % echo ${mingyan//good/hao}haohaostudy,daydayup!
获取字符串的长度
string-name,#加字符串变量名
#!/bin/bashstr="shenshuai89@qq.com"echo ${#str}
字符串拼接合并
Shell 中你不需要使用任何运算符,将两个字符串并排放在一起就能实现拼接
#!/bin/bashemail="shenshuai89@qq.com"username="北鸟南游"str1=$username$email #中间不能有空格str2="$username $email" #如果被双引号包围,那么中间可以有空格str3=$username": "$email #中间可以出现别的字符串str4="$username: $email" #这样写也可以str5="${username}Script: ${email}index.html" #这个时候需要给变量名加上大括号echo $str1echo $str2echo $str3echo $str4echo $str5
字符串截取
从指定位置开始截取
这种方式需要两个参数:除了指定起始位置,还需要截取长度${string: start :length},length 是要截取的长度(省略的话表示直到字符串的末尾)
#!/bin/bashemail="shenshuai89@qq.com"echo ${email: 4: 7}# 输出shuai89
从右侧开始计数
从字符串的右边开始计数${string: 0-start :length},从右侧计数,要从1开始
#!/bin/bashemail="shenshuai89@qq.com"echo ${email: 0-14: 7}
从指定字符(子字符串)开始截取
这种截取方式无法指定字符串长度,只能从指定字符(子字符串)截取到字符串末尾。Shell 可以截取指定字符(子字符串)右边的所有字符,也可以截取左边的所有字符。
- 使用 # 号截取右边字符 ${string#*chars}
- 使用 号截取右边字符 ${string%chars}
如果有多个符号条件,希望直到最后一个指定字符(子字符串)再匹配结束,那么可以使用##或者**#! /bin/bashemail="shenshuai89@qq.com"echo ${email#*shuai}echo ${email%shuai*}# 89@qq.com# shen
#! /bin/bashemail="shenshuai89@qq.com"echo ${email#*sh}echo ${email##*sh}# enshuai89@qq.com# uai89@qq.com
数组
定义数组,使用()
Shell 中,用括号( )来表示数组,数组元素之间用空格来分隔 ```bash!/bin/bash
arr=(1 2 3) echo “${arr[2]}”
Shell 是弱类型的,它并不要求所有数组元素的类型必须相同
arr=(23 34 ‘defineArray’) echo “${arr[2]}”
⚠️注意:赋值号=两边不能有空格,必须紧挨着数组名和数组元素<a name="JOCR4"></a>### 数组增加元素shell定义的数组长度是不固定的,定义之后还可以增加元素。```bash#!/bin/bash# 给数组增加元素names=('sam' 'shenshuai')names[2]='beiniaonanyou'echo ${names[2]}# 获取数组中的所有元素${arr[*]}echo ${names[*]}# 获取数组长度 ${#arr[*]}echo ${#names[*]}
数组拼接
将两个数组连接成一个数组,利用@或*,将数组扩展成列表,然后再合并到一起
#!/bin/basharr1=(1 3 5)arr2=('string' 'number')arrAll=(${arr1[*]} ${arr2[*]})echo ${arrAll[*]}
删除数组元素
shell使用 unset 关键字来删除数组元素 unset array_name[index]
#!/bin/bashunset arrAll[2]echo ${arrAll[*]}# 删除数组全部unset arrAllecho ${arrAll[*]}
read获取输入
read用来从标准输入中读取数据并赋值给变量。默认就是从键盘读取用户输入的数据;
语法: read [options] [values]
| -p prompt | 显示提示信息,提示内容为 prompt。 |
|---|---|
| -r | 原样读取(Raw mode),不把反斜杠字符解释为转义字符 |
| -s | 静默模式(Silent mode),不会在屏幕上显示输入的字符。当输入密码和其它确认信息的时候,这是很有必要的 |
| -n num | 读取 num 个字符,而不是整行字符。 |
#!/bin/bashread -p "input your name age > " name ageecho "名字:$name"echo "年龄:$age"
运算
(())
双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,
((表达式)):将数学运算表达式放在(())中
echo $((1+1))echo $((2-1))echo $((2*2))echo $((2/1))echo $((8<3))
let
let的作用和(())类似,都是对数据进行运算。
两者都是只能处理整数,不能处理小数或字符串。
a=10 b=20let c=a+becho c
expr
expr运算,数字和运算符号中间要有空格,否则会被当作字符串输出。
乘号*要做转义处理
#!/bin/bash# 两个数字运算,中间要留空格,否则会当作完整字符串输出expr 1 + 1 #2expr 5 - 2 #3expr 2 \* 7 #14expr 5 / 2 #2
条件语句
if else
read aread bif (($a == $b))thenecho "a==b"elseecho "a!=b"fi
if elif else
echo 'input age number'read ageif (($age <=2));then echo '婴儿';elif (($age >=3 && $age <=8 )); thenecho '幼儿';elif (($age >=9 && $age <=17)); thenecho '少年';elif (( $age >=18 && $age <= 25))then echo '成年'elif (( $age >= 26 && $age <= 40))then echo '青年'elif (($age>=41 && $age <=60))then echo '中年'elseecho '老年'fi
printf 'input integer number: 'read numif (($num == 1)); then echo 'Monday';elif (($num ==2));then echo 'Tuesday';elif (($num ==3));then echo 'Wednesday';elif (($num ==4));then echo 'Thursday';elif (($num==5)); then echo 'Friday';elif (($num==6)); then echo 'Saturday';elif (($num==7)); then echo 'Sunday';else 'error';fi
case
printf "input integer number: "read numcase $num in1)echo "Monday";;2)echo "Tuesday";;3)echo "Wednesday";;4)echo "Thursday";;5)echo "Friday";;6)echo "Saturday";;7)echo "Sunday";;*)echo "error"esac
while
i=1sum=0while ((i<=100))do((sum += i))((i++))doneecho "result: $sum"
sum=0echo "请输入您要计算的数字,按 Ctrl+D 组合键结束读取"while read ndo((sum += n))doneecho "sum result: $sum"
for
sum=0for ((i=0; i<=100; i++))do((sum += i))doneecho "result sum: $sum"
break continue
break
使用 while、until、for、select 循环时,如果想提前结束循环,可以使用 break 或者 continue 关键字。
#!/bin/bashsum=0while read n; doif ((n>0));then((sum+=n))elsebreakfidoneecho "sum is $sum
Shell 中的 break 和 continue 能够跳出多层循环;break n或者continue n,默认跳出当前循环
#!/bin/bashi=0while ((++i)); doj=0while ((++j)); doif ((i>4)); thenbreak 2fiif ((j>4));thenbreakfiprintf "%-4d" $((i*j))doneprintf "\n"done
第7行表示跳出2层循环;
break 用来结束所有循环,循环语句不再有执行的机会;continue 用来结束本次循环,直接跳到下一次循环,如果循环条件成立,还会继续循环。
continue
跳出当前循环,100以内的值相加,使用ctrl+d结束
#!/bin/bashsum=0while read n; doif ((n<1 || n>100)); thencontinuefi((sum+=n))doneecho "sum=$sum"
不跳出循环
printf中 %d 的意思是按照整数格式输出后面的第一个参数的值。 printf中 %-4d的意思:输出一个int型数,4位宽度,左对齐。后面若还有输出项时,n的输出至少占4位,不足4位时,后面补空格到4位;若超过4位时,按实际宽度输出n的值。
#!/bin/bashfor ((i=1; i<=9; i++)); dofor ((j=1; j<=9; j++)); doprintf "%d*%d=%-4d" $i $j $((i*j))doneprintf "\n"done
1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=92*1=2 2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=183*1=3 3*2=6 3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=274*1=4 4*2=8 4*3=12 4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=365*1=5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=456*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 6*7=42 6*8=48 6*9=547*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=638*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 8*9=729*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
条件添加,退出多层循环
for ((i=1; i<=9; i++)); dofor ((j=1; j<=9; j++)); doif ((i<j)); thenprintf "\n"continue 2fiprintf "%d*%d=%-4d" $i $j $((i*j))doneprintf "\n"done
1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94*1=4 4*2=8 4*3=12 4*4=165*1=5 5*2=10 5*3=15 5*4=20 5*5=256*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=367*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=498*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=649*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
select in
select in是增强交互,可以将in后的值按照编号显示输出。用户选择不同的编号,执行不同的操作。
select in 是 Shell 独有的一种循环,非常适合终端(Terminal)这样的交互场景。
#!/bin/bashecho "What is your favourite OS?"select name in "Linux" "Windows" "Mac OS" "UNIX" "Android"doecho $namedoneecho "You have selected $name"
⚠️注意,select 是无限循环(死循环),输入空值,或者输入的值无效,都不会结束循环,只有遇到 break 语句,或者按下 Ctrl+D 组合键才能结束循环。
select in通常和case in一起使用,用户选择不同序号执行不同程序。
echo "which is your love os?"select name in "Linux" "windows" "mac" "unix" "android"docase $name in"Linux")echo "Linux是一个类UNIX操作系统,它开源免费,运行在各种服务器设备和嵌入式设备。"break;;"windows")echo "Windows是微软开发的个人电脑操作系统,它是闭源收费的。"break;;"mac")echo "Mac OS是苹果公司基于UNIX开发的一款图形界面操作系统,只能运行与苹果提供的硬件之上。"break;;"unix")echo "UNIX是操作系统的开山鼻祖,现在已经逐渐退出历史舞台,只应用在特殊场合。"break;;"android")echo "Android是由Google开发的手机操作系统,目前已经占据了70%的市场份额。"break;;*)echo "输入错误,请重新输入"esacdoneecho "you have selected $name"
函数
Shell 函数的本质是一段可以重复使用的脚本代码,使用时直接调用即可。
shell函数语法
function name() {statements[return value]}
定义一个函数,计算所有参数的和
#!/bin/bashfunction getsum(){local sum=0for n in $*do((sum+=n))donereturn $sum}getsum 10 20 30echo $?
$*表示所有参数,$?表示函数的退出状态(返回值)
参考文档:
c语言编程
http://c.biancheng.net/view/706.html
阿里云课堂
https://edu.aliyun.com/course/155/lesson/list?utm_content=m_1000297219
shell编程范例
https://tinylab-1.gitbook.io/shellbook/01-chapter1
