shell脚本快速入门

2,930 阅读6分钟

shell脚本类别

shell脚本有sh、bash、ksh、csh、zsh等等,不同的shell脚本都有自己的特点,但用法是差不多的,Mac自带shell,可以用cat /etc/shells去查看,本文为Windows环境中使用bash。

shell脚本能做什么?

  1. 将一些复杂的命令简单化(平时我们提交一次代码可能需要很多步骤,但是可以用Shell简化成一步);
  2. 解决很多重复性操作(比如多次修改相同的文件内容);
  3. 自动打包、编译、发布等功能;

所以只要有规律可循的操作都可以用shell去尝试一下,大大提高搬砖效率。

第一个shell脚本

新建一个test.sh的记事本,扩展名为 sh(sh代表shell),输入以下内容:

#!/bin/bash
echo 'hello world!'

第一行的#!是一个约定标记,指定这里使用bash这个解释器来解释这个脚本,这一行一般必须写明。 第二行的echo命令是在屏幕上输出hello world!。

如何运行

  1. 在git bash中进入到test.sh所在文件夹目录;
  2. 输入./test.sh执行脚本;

注意:一定要写成./test.sh,不可以写成test.sh,目的是用 ./test.sh 告诉系统说,就在当前目录找,不然写成 test.sh 是会找不到命令的。

运行结果:

运行结果

到这里一个最简单的shell脚本就完成了,接下来就来看看更深入一点的内容吧!

shell 变量

定义变量时,变量名不加美元符号$,如:

name=chenying

需要注意的是,和别的语言不一样的是:变量名和等号之间不能有空格

使用一个定义过的变量,只要在变量名前面加美元符号即可,至于后的花括号,加不加都可,但还是建议加上,养成一个好的编程习惯,如:

name=chenying
echo $name
echo ${name}

shell变量分为局部变量(变量前面加local)和全局变量(变量前面不添加),局部变量的可见范围是代码块或函数内,全局变量则全局可见,和别的语言类似。

shell 字符串

字符串可以用单引号,也可以用双引号。

区别

单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的,也不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

双引号里可以有变量,双引号里可以出现转义字符。

单引号栗子:

str='this is a string'

双引号栗子:

name='Isabella'
str="Hello, I know you are \"$name\"! \n"
echo -e $str

其中, echo -e 表示使用转义功能。

拼接字符串

name='Isabella'
#使用双引号拼接
a="hello, "$name" !"
b="hello, ${name} !"
echo $a $b
#使用单引号拼接
a1='hello, '$name' !'
b1='hello, ${name} !'
echo $a1 $b1 

输出结果

hello, Isabella ! hello, Isabella !
hello, Isabella ! hello, ${name} !

获取字符串长度

string="Isabella"
echo ${#string} #输出 8

截取字符串

此栗子从字符串第 3 个字符开始截取 6 个字符:

string="Corgi is so cute!"
echo ${string:2:6} # 输出 rgi is

查找子字符串

查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):

string="Corgi is so cute!"
echo `expr index "$string" io` # 输出 2

shell 传递参数

脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推。 栗子:

#!/bin/bash
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

执行./test.sh a b c,输出结果为:

第一个参数为:a
第二个参数为:b
第三个参数为:c

工作应用场景:

#!/bin/bash
# 从传参获取分支名
branch=${1}
if [ ${#branch} = 0 ]
then
    echo "请输入分支名"
    exit 1
fi
echo ${branch}
# 子模块路径
subPath="d:/projects/web-ac-course-new-ngk0/src/input/dist/"
# 切换到子模块目录
cd ${subPath}
#切换到当前传参的分支
git checkout ngk0-${branch}

执行./test.sh 221,输出结果为:

221
Switched to branch 'ngk0-221'
Your branch is up to date with 'origin/ngk0-221'.

shell 基本运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

算术运算符

加+ 减- 乘* 除/ 取余% 赋值= 相等== 不相等!=

求和栗子:

#!/bin/bash

val=`expr 1 + 1`
echo "两数之和为 : $val" #输出结果:2

注:

  1. 表达式和运算符之间要有空格,例如 1+1 是不对的,必须写成1 + 1
  2. 整的表达式要被 ` ` 包含;

算术运算符栗子:

#!/bin/bash

a=10
b=20

val=`expr $a + $b`
echo "a + b : $val"

val=`expr $a - $b`
echo "a - b : $val"

val=`expr $a \* $b`
echo "a * b : $val"

val=`expr $b / $a`
echo "b / a : $val"

val=`expr $b % $a`
echo "b % a : $val"

if [ $a == $b ]
then
   echo "a 等于 b"
fi
if [ $a != $b ]
then
   echo "a 不等于 b"
fi

输出结果:

a + b : 30
a - b : -10
a * b : 200
b / a : 2
b % a : 0
a 不等于 b

还有关系运算符、布尔运算符、逻辑运算符、字符串运算符、文件测试运算符可参考菜鸟教程shell运算符

shell 流程控制

if else

语法格式

if condition
then
    command1 
    command2
    ...
    commandN 
fi

栗子

num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
    echo '两个数字相等!'
else
    echo '两个数字不相等!'
fi # 两个数字相等!

if else-if else

语法格式

if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

栗子

#判断两个变量是否相等
a=10
b=20
if [ $a == $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi # a 小于 b

for 循环

语法格式

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

数字型循环

#1
for((i=1;i<=10;i++));  
do   
echo $(expr $i \* 3 + 1);  
done
#2
for i in $(seq 1 10)  
do   
echo $(expr $i \* 3 + 1);  
done 
#3
for i in `seq 10`  
do   
echo $(expr $i \* 3 + 1);  
done
#4
for i in {1..10}  
do  
echo $(expr $i \* 3 + 1);  
done 

字符型循环

#遍历出当前文件目录中的文件名
for i in `ls`;  
do   
echo $i is file name\! ;  
done 
#遍历出空格前后的内容
list="corgi is so cute !"  
for i in $list;  
do  
echo $i is block ;  
done 

while 语句

语法格式

while condition
do
    command
done

until 循环

until 循环执行一系列命令直至条件为 true 时停止,与 while 循环在处理方式上刚好相反。 语法格式

until condition
do
    command
done

case

shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令,语法格式:

casein
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac #需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break

跳出循环

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。

shell 函数

简化写法中function可以不写,语法格式

function name() {
    statements
    [return value]
}

工作中应用场景:

# 提交代码
function pushCode() {
    git add .
    git commit -m 'feat: 新增视频语音包'
    git pull
    git push
}
pushCode

Linux 三剑客简单介绍(grep、sed、awk)

grep擅长查找功能,sed擅长取行和替换。awk擅长取列。

1. grep

语法

grep [OPTIONS] PATTERN [FILE...]

注:这里的模式,要么是字符(串),要么是正则表达式。

grep常用选项如下:

选项 含义
-c 仅列出文件中包含模式的行数。
-i 忽略模式中的字母大小写。
-l 列出带有匹配行的文件名。
-n 在每一行的最前面列出行号。
-v 列出没有匹配模式的行。
-w 把表达式当做一个完整的单字符来搜寻,忽略那些部分匹配的行。

栗子:

1、在指定文件(dataPath="d:/projects/web-ac-course-new-ngk2/src/input/dist/data.js")中查找并打印包含"PureImage"的行

grep "PureImage" ${dataPath}

输出结果

dataList.PureImage = {

2、忽略大小写搜索(-i)

grep -i "pureiimage" ${dataPath}

输出结果

dataList.PureImage = {

3、统计字符串出现的次数(-c)

grep -c "show" ${dataPath} #17
grep -n "show" ${dataPath} 

-n 可以列出匹配的字符串所在行号以及所在行内容。

4、高亮显示匹配内容(--color)

grep --color "PureImage" ${dataPath}

5、双重条件匹配 匹配当前目录中包含float的文件并高亮。

ls *.html | grep --color "float"

2. sed

语法

sed [option]... 'script' inputfile

sed常用选项如下:

选项 含义
-e 可以在同一行里执行多条命令
-f 后跟保存了sed指令的文件
-i 直接对内容进行修改,不加-i时默认只是预览,不会对文件做实际修改
-n sed默认会输出所有文本内容,使用-n参数后只显示处理过的行

sed常用编辑命令:

命令 含义
a 向匹配行后面插入内容
i 向匹配行前插入内容
c 更改匹配行的内容
d 删除匹配的内容
s 替换掉匹配的内容
p 打印出匹配的内容,通常与-n选项一起使用

栗子:

1、一行命令替换多处内容,不加-e只能替换第一处的内容

sed -e 's/abc/qqq/g' -e 's/123/999/g' data.js

2、向文件中添加或插入行(a/i)

#在第2行后添加hello
sed '2ahello' data.js

#向匹配内容123后面添加hello,如果文件中有多行包括123,则每一行后面都会添加
sed '/123/ahello' data.js

#最后一行添加hello
sed '$ahello' data.js

在匹配内容之前插入只需把a换成i

3、替换匹配行内容(c)

#把文件的第1行替换为hello
sed '1chello' data.js

4、删除匹配行(d)

#删除第2行
sed '2d' data.js

#从第一行开始删除,每隔2行就删掉一行,即删除奇数行
sed '1~2d' data.js
#删除1~2行
sed '1,2d' data.js
#删除1~2之外的行
sed '1,2!d' data.js
#删除不匹配123或abc的行,/123\|abc/ 表示匹配123或abc ,!表示取反
sed '/123\|abc/!d' data.js

5、替换文件中的内容(s)

#替换每行第1个123为hello
sed 's/123/hello/' data.js
#替换每行第2个123为hello
sed 's/123/hello/2' data.js
#替换,后面的内容为空
sed 's/,.*//g' data.js

以上这些栗子都不会修改原文件,一般这些命令都是配合sed选项来用,如想修改原文件需要加上-i这个选项,否则只是预览效果。

3. awk

awk支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。 语法

awk [options] 'script' var=value file(s) 
awk [options] -f scriptfile var=value file(s)

常用选项

选项 含义
-F fs fs 指定输入分隔符,fs可以时字符串或正则表达式
-v var=value 赋值一个用户定义变量,将外部变量传递给awk
-f scriptfile 从脚本文件中读取awk命令