shell脚本核心

本文梳理linux的shell脚本知识,linux基础部分的前提知识点击这里linux核心知识梳理

一、脚本基础

1、简介

Linux Shell脚本有很多

Bourne Shell(sh) 命令文件 /usr/bin/sh或/bin/sh
Bourne Again shell(bash)命令文件 /bin/bash
C Shell(csh)命令文件 /usr/bin/csh
TENEX C Shell(tcsh)
Korn shell(ksh)命令文件 /usr/bin/ksh
Shell for Root(/sbin/sh)
…

Bash 是目前最常用的 Shell,除非特别指明,下文的 Shell 和 Bash 当作同义词使用,可以互换。

2、echo打印

声明为bin类型的bash脚本:固定写法

注释:以#开头

echo:打印

#!/bin/bash
# 这是注释
echo "123"

3、声明变量注意

声明变量的”=“前后不能有空格,否则脚本报错

注意:赋值时 “=” 两边都不能加空格符;比较时 “=” 两边都必须加空格符。

#!/bin/bash
# 字符串
text="I love china!"
echo $text
# 数字
NDK=10
echo $NDK
# 拼接
echo "$text haha"
# 转义输出
echo "\$NDK"

打印

I love china!
10
I love china! haha
$NDK

4、系统日期、用户名

#!/bin/bash
date
who

输出时间和用户名

2022年 7月11日 星期一 09时11分25秒 CST
zhanglei console Jun 28 19:54 zhanglei ttys000 Jul 11 08:52

二、shell各种括号的用法 () (())、[]、[[]]、{}

1、() 运算符

1.1、命令替换 $()
#!/bin/bash

date
# 命令替换就是将shell命令的输出赋给变量
test=$(date)
echo $test
# 除了使用$() 进行命令替换以外,还可以用 `` 符号
test2=`date`
echo $test2
1.2、进程列表 (;;)

() 表示在当前 shell 中将多个命令作为一个整体执行,示例:

# 它的一般形式为: ( 命令;命令;命令… )
rm ~/Desktop/1.txt || (cd ~/Desktop/;ls -a;echo "fail")

每个命令后面加分号就是命令列表,但是同样的命令列表括号的加入使命令列表变成了进程列表。下面示例中$BASH_SUBSHELL 输出为0则表示为主线程。

#!/bin/bash

# /Users/zhanglei/Desktop
# 1
(pwd ;echo  $BASH_SUBSHELL )

# /Users/zhanglei/Desktop
# 0
pwd ;echo  $BASH_SUBSHELL
1.3、数组变量(a b c d )

在shell 中也是支持定义数组的,数组的赋值是通过()括起来的,数组元素之间通过空格分隔,并且数组的下标是从零开始的。其中和其他编译语言一样要访问数组元素需要通过数组名+[下标]的方式访问。[*] 比较特别,它可以列出数组的所有元素。并且变量名指代的是数组变量的第一个元素也就是[0]。

#!/bin/bash

test=(a b c d)
echo ${test[*]}		# a b c d
echo ${test[0]}		# a
echo $test				# a

2、(()) 运算符

注意:

  1. expr的乘法需要转义
  2. 这两者都只能用于整数的计算,对于浮点数计算会直接报错
2.1、(())加减乘除

用于计算整数的加减乘除

#!/bin/bash
a=10
b=20

c2=$(($a + $b))
echo "加:$c2"
echo "减:$(($b - $a))"
echo "乘:$(($b * $a))"
echo "除:$(($b / $a))"
加:30
减:10
乘:200
乘:2
2.2、expr加减乘除

expr命令,是一个手工命令行计数器,用于在Linux下求表达式变量的值,一般用于整数值,也可用于字符串。

#!/bin/bash
a=10
b=20

c=$(expr $b + $a)
echo "加:$c"
echo "减:$(expr $b - $a)"
echo "乘:$(expr $b \* $a)"
echo "除:$(expr $b / $a)"
加:30
减:10
乘:200
乘:2

3、[] 运算符

3.1、通配符[]
  • 查找1或3的文件

中括号表示一个字符位置并给出多个可能的选择

➜  未命名文件夹 ls
123     223     323     tests.c
➜  未命名文件夹 ls [13]*
123 323
  • 查找字母范围[1–3]的文件

-表示指定范围

➜  未命名文件夹 ls
123     223     323     tests.c
➜  未命名文件夹 ls [1-3]*
123 223 323
3.2、数学运算$[]

只能用于整数的加、乘

#!/bin/bash
a=10
b=20

c3=$[$a + $b]
echo "加:$c3"
echo "乘:$[$a * $b]"
加:30
乘:200

4、[[]]运算符

模式匹配比较 [[]] ,更多参考[5.1、字符串判断](# 1、字符串判断)

if [[ str1 ]]          # 当字符串 str1 为非空时为真

5、{}运算符

5.1、变量范围限定${}
#!/bin/bash

a=123456
echo $abc		#
echo ${a}bc	#123456bc
5.2、命令分组 { ;;}

注意 “{” 后面需要有空格,“}” 前可以不需要空格 但是最后一条命令需要结束后也需要加“;” 。可以看到echo $BASH_SUBSHELL 输出的为 0,说明命令分组 { ;;} 并没有创建子shell 执行命令。

#!/bin/bash

{ ls ; ls ;echo  $BASH_SUBSHELL; }

# 123  223  323  tests.c
# 0

二、计算

1、浮点数

bc:浮点数计算

|: 管道,一个命令的输出作为另外一个命令的输入

scale:自带的内建变量,设定小数位数

#!/bin/bash
a=10
b=20

e=$(echo "scale=4; $a / 3" | bc)
echo "浮点数计算:$e"
浮点数计算:3.3333

2、内联输入重定向

bc:浮点数计算

scale:自带的内建变量,设定小数位数

格式相对固定:

  1. 开头:$(bc << EOF,

  2. 结尾:EOF)

示例中:将 bc 的计算结果赋值给 Shell 变量

#!/bin/bash
a=10
b=20

f=$(bc << EOF
scale=4
a1=$a * $b
a1/3
EOF
)
echo "内联输入重定向:$f"
内联输入重定向:66.6666

3、&&和||

shell支持逻辑运算符编写命令语句

command1  && command2 //逻辑与:如果这个命令执行成功&&那么执行这个命令
command1 || command2	//逻辑或:如果这个命令执行失败了||那么就执行这个命令

4、异步执行

4.1、&异步执行

在执行命令后加&操作符,表示将命令放在子shell中异步执行。可以达到多线程效果。如下

sleep 10 #等待10秒,再继续下一操作  
sleep 10 & #当前shell不等待,后台子shell等待  
4.2、wait命令

等待作业号或者进程号制定的进程退出

#!/bin/bash  
sleep 10 &  
sleep 5&  
wait #等待10秒后,退出  

四、条件语句

1、if

  1. If里面必须要then,else里面可以不用then
  2. fi结尾
  3. grep:文本搜索工具命令

下面示例:去读是linux下否有自定义的jack用户,有则打印jack的主目录,无则提示。关于怎么创建用户参考linux核心知识梳理

#!/bin/bash
testuser=jack
if grep $testuser /etc/passwd
then
    echo "ok"
    ls -a /home/$testuser/
elif ls -d /home/$testuser
then
    echo "用户不存在,主目录仍然存在"
else
    echo "$testuser not exist"
fi
jack:x:1002:1002::/home/jack:/bin/sh
ok
.  ..  .bash_logout  .bashrc  .profile

passwd:当前所有用户信息,linux下截图如下

image-20220127202810611

2、test

test命令,如果条件成立,test命令状态为0退出,if条件成立

下面示例中:判断var变量是否有值(0也是有值),这里为字符串abc,因此if成立

#!/bin/bash
var=abc
if test $var
then
	echo "test条件成立"
else
	echo "test条件不成立"
fi
test条件成立

3、多个条件

3.1、操作符[ ]

如果if要判断多个条件,我们&&将多个[ ]连接起来

-d:检查目录是否存在

-w:检查是否存在,并且可写

下面示例:在指定目录下生成了test5文件

#!/bin/bash
#多个条件 []
mydir=/Users/zhanglei/Desktop
#任意数学赋值或者比较表达式
#if (( a++ > 90 ))
if [ -d $HOME ] && [ -w $mydir ]
then
 cd $mydir
 touch test5
else
 echo "no"
fi
3.2、操作符 (( ))

下面示例输出:yes

#!/bin/bash
#多个条件 []
#任意数学赋值或者比较表达式
a=95
if (( (a++ > 90) && (a++ < 100) ))
then
	echo "yes"
else
	echo "no"
fi

4、case语句

case命令
case 变量 in
pattern1) 命令;;
pattern2) 命令;;
*) 默认命令;;
esac

  1. 每个case用)包起来,也就是:jack)
  2. 每个case末尾用双分号:;;
  3. default用esac
#!/bin/bash
testuser=jack

case $testuser in
jack)
	echo "hi,rose with jack";;
jason)
	echo "hello,jason";;
*)
	echo "defaults";;
esac

输出

hi,rose with jack

五、判断语句

1、字符串判断

if [[ str1 = str2 ]]   # 当字符串 str1 和 str2 有相同内容、长度时为真
if [[ str1 != str2 ]]  # 当字符串 str1 和 str2 不等时为真
if [[ -n "str1" ]]     # 当字符串 str1 的长度大于 0(非空)时为真 
if [[ -z "str1" ]]	   # 当字符串 str1 的长度为 0(空)时为真 
if [[ str1 ]]          # 当字符串 str1 为非空时为真

示例

结果:相等

#!/bin/bash
str1="asdf"
str2="asdf"
if [[ str1 = str2 ]]; then
  echo "相等"
else
  echo "不相等"
fi

注意:

  1. 赋值时 “=” 两边都不能加空格符;比较时 “=” 两边都必须加空格符。
  2. 字符串比较这里=前后空格

== 和=

  1. ==可用于判断变量是否相等,= 除了可用于判断变量是否相等外,还可以表示赋值。
  2. = 与 == 在 [ ] 中表示判断(字符串比较)时是等价的
  3. 在 (( )) 中 = 表示赋值, == 表示判断(整数比较),它们不等价

2、数字的判断

int1 -eq int2    # 两数相等为真
int1 -ne int2    # 两数不等为真
int1 -gt int2    # int1大于int2为真
int1 -ge int2    # int1大于等于int2为真
int1 -lt int2    # int1小于int2为真
int1 -le int2    # int1小于等于int2为真

下面示例输出:10 greater than 5

if[ ]:test命令简单形式

注意:if[ ]要打前后空格

#!/bin/bash
int1=10
int2=5
if [ $int1 -gt $int2 ]
then
    echo "$int1 greater than $int2"
else
    echo "$int1 smaller than $int2"
fi

3、文件的判断

# 高频
-d file     # 文件为目录为真
-e file     # 检查file是否存在
-f file     # 文件为正规文件为真(检查是否存在,并且是一个文件)
# 非高频
-c file     # 文件为字符特殊文件为真
-b file     # 文件为块特殊文件为真
-s file     # 文件大小非0时为真
-t file     # 当文件描述符(默认为1)指定的设备为终端时为真

# rwx读、写、执行
-r file     # 用户可读为真
-w file     # 用户可写为真
-x file     # 用户可执行为真

示例:-d检查目录是否存在

#!/bin/bash
mydir=/Users/zhanglei/Desktop
#-d检查目录是否存在
if [ -d $mydir ]
then
	echo "$mydir exist"
	cd $mydir
	ls
else
	echo "mydir not exist"
fi
 exist
 01.sh                           U启动增强版.lnk                 min-apps-develop                test_cli

六、循环语句

1、for循环

分隔符IFS:”IFS=-“就是以-为分隔符

#!/bin/bash

list="windows--linux--macos"
#IFS字段分隔符
#IFS=$--
IFS=-
for item in $list
do
	echo $item
done
windows

linux

macos

2、while循环

-gt:大于

-eq:等于

下面示例:a的值为5,a>0时每次循环减1,当a=5退出循环

#!/bin/bash

a=10
while [ $a -gt 0 ]
do
	echo "num:$a"
	#赋值不用使用$符号
	a=$[ $a - 1 ]
	if [ $a -eq 5 ]
	then
		echo "break"
		break
	fi
done
num:10
num:9
num:8
num:7
num:6
break

七、脚本文件入参

1、第一个参数、第二个参数

$0:表示文件路径

$1:表示第一个参数

$2:表示第二个参数,以此类推

#!/bin/bash
echo $0
echo $1
echo $2

使用两种不同方式调用脚本输出如下

➜  Desktop sh test.sh 123 456
test.sh
123
456
➜  Desktop ./test.sh 123 456
./test.sh
123
456

2、获取文件名与参数总数

#!/bin/bash

filename=$(basename $0)
echo $filename
echo "参数的总数:$#"

使用两种不同方式调用脚本输出如下

➜  Desktop sh test.sh 123 456
test.sh
参数的总数:2
➜  Desktop ./test.sh 123 456 
test.sh
参数的总数:2

3、for循环遍历参数

#!/bin/bash

#使用$@遍历所有参数
for param in "$@"
do
	echo "param:$param"
done
➜  Desktop ./test.sh 123 456 789
param:123
param:456
param:789

八、输出重定向

1、ls命令的重定向

输出到一个文件

#!/bin/bash
ls -la > text3.txt

将文件列表输出到text3.txt文件中

total 432
drwx------+ 27 zhanglei  staff     864  7 11 09:00 .
drwxr-x---+ 88 zhanglei  staff    2816  7 11 09:00 ..

2、所有的输出重定向

上面仅针对一条命令进行重定向,那么如何对后续所有输出重定向?

exec num输出重定向,num取值
0:STDIN 标准输入(光标等待用户输入的)
1:STDOUT 标准输出
2:STDERR 标准错误

#!/bin/bash

exec 1>test7.txt

echo "abc"
echo "efg"
ls -a

打印如下 (可以用来写日志)

abc
efg
test7.txt
test.sh

九、函数

1、函数入参与返回值

示例:调用myfun函数传入10、90两个参数,相加后通过echo返回,得到100赋值给value

注意:函数括号不能紧贴函数写,错误写法”myfun{“,这里要么换行要么空格

#!/bin/bash

function myfun
{
	echo $[ $1 + $2 ]
}

value=$(myfun 10 90)
echo "value:$value"

打印如下

➜  Desktop ./test.sh
value:asdf 100
1.1、返回值的方式
  • 方法一:return
  • 方法二: echo
1.2、return和echo使用场景区别:
  • 使用return返回值:

使用return返回值,只能返回1-255的整数

函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0表示成功,1表示失败

  • 使用echo返回值:

使用echo可以返回任何字符串结果

通常用于返回数据,比如一个字符串值或者列表值

2、引入其他脚本文件

如果是调用其它脚本,直接bash 脚本全路径即可

bash ./replace/replaceResources.sh

如果是引入其他脚本变量函数,则需要source引入。

比如这里定义加法函数add.sh如下

#!/bin/bash

function add()
{
	echo $[ $1 + $2 ]
}
2.1、source引入

新建脚本source引入add.sh,并调用add函数

#!/bin/bash

#引入
source ./add.sh
echo "add:$(add 10 30)"

#打印:add:40
2.2、.source快捷别名

注意第一个点是快捷别名,第二个点是路径,不能写连一块儿

#!/bin/bash

#.source快捷别名
. ./add.sh
echo "add:$(add 10 30)"

#打印:add:40
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流星雨在线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值