Shell教程

Shell编程跟JavaScript、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。Linux的Shell中类众多,可以使用以下指令直到系统支持的Shell类型:

zhudk@vm1:~$ cat /etc/shells
zhudk@vm1:~$ cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/bin/zsh
/usr/bin/zsh

若想知道Bash的绝对路径,可在终端中输入命令:

zhudk@vm1:~$ which bash

本教程关注的是Bash,由于易用和免费,Bash在日常工作中被广泛使用。同时,Bash也是大多数Linux系统默认的Shell。所以在shell脚本中第一行一般是这样:

#!/bin/bash

#!是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种shell。

echo "hello world!!!"

echo命令用于向窗口输出文本。

Shell变量

定义变量
my_name="bobo"

除了上述地显示赋值,还可以用语句给变量赋值:

for file in $(ls ./);do
	echo ${file}
done
使用变量
echo ${my_name}
my_name="helan"
echo ${my_name}
只读变量
readonly myUrl="https://www.google.com"
myUrl="https://www.baidu.com" #会报错
删除变量
my_name="bobo"
unset my_name
echo ${my_name} #实际没有任何输出,因为被删除了。不能删除readonly变量,会报错。
变量类型

运行shell时,会同时存在三种变量:

局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。

环境变量:所有的陈虚谷,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。您可以在终端输入命令set,env,printenv以获取这些变量的列表。

shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分时环境变量,有一部分是局部变量,这些变量保证了shell的正常运行。

Shell字符串
my_name="Bobo"

str="hi,are you \"${my_name}\"?"  #\用于转义
echo ${str}
获取字符串长度
my_name="Bobo"
echo ${#my_name}
提取子字符串
my_name="hi,i am Bobo!"
echo ${my_name:0:4}  #从索引为0开始的字符提取,提取4个字符
查找字符串
my_name="hi,i am Bobo!"
#查找字符i或者o出现的位置(位置=索引+1)
echo `expr index "${my_name}" io`
Shell数组
定义数组
nums=(10 20 30 40 50)
names=("Bobo" "Jame" "Paul" "Jone")

元素之间使用空格分开。

使用数组
#获取数组中的某一个元素
echo ${nums[2]}
echo ${names[3]}

#获取数组中的所有元素
echo ${names[@]}

#获取数组元素的个数
echo ${#names[@]}

#获取某个元素的长度
echo ${#names[3]}
Shell传递参数

我们可以在执行shell脚本时,像脚本传递参数,脚本内获取参数的格式为$n。n代表一个数字:

  • 0为执行的文件名(包含文件路径)
  • 1为执行脚本的第一个参数
  • 2为执行脚本的第二个参数,
  • 以此类推。。。
echo "传递参数"
echo "执行的文件名:$0"
echo "执行的文件名:$1"
echo "执行的文件名:$2"
$ ./build.sh 1 hello
传递参数
执行的文件名:./build.sh
执行的文件名:1
执行的文件名:hello

传递的参数在后面以空格分开。

还有几个特殊字符可用来处理参数:

$#:传递到脚本的参数个数。

$*:将所有参数组成一个单字符串(一个参数)。

$@:将每一个参数作为字符串(多个参数)。

echo "传递参数"
echo "执行的文件名:$0"
echo "执行的文件名:$1"
echo "执行的文件名:$2"
echo "所有的参数作为一个字符串:$*"
echo "所有的参数作\$@:$@"

我们再来看看$*$@的区别:

echo "....\$*...."
for i in "$*";do
	echo $i
done

echo "....\$@...."
for i in "$@";do
	echo $i
done
$ ./build.sh 1 hello
....$*....
1 hello
....$@....
1
hello
Shell基本运算符

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

算术运算符
运算符说明举例
+加法expr $a + $b 结果为 30。
-减法expr $a - $b 结果为 -10。
*乘法expr $a \* $b 结果为 200。
/除法expr $b / $a 结果为 2。
%取余expr $b % $a 结果为 0。
=赋值a=$b 把变量 b 的值赋给 a。
==相等。用于比较两个数字,相同则返回 true。[ $a == $b ] 返回 false。
!=不相等。用于比较两个数字,不相同则返回 true。[ $a != $b ] 返回 true。
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 $a / $b`
echo "a / b = ${val}"

val=`expr $a % $b`
echo "a % b = ${val}"

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

if [ $a != $b ]
then
	echo "a不等于b"
fi
关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值时数字。

运算符说明举例
-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。
a=10
b=20
if [ $a -eq $b ]
then
	echo "$a -eq $b : a等于b"
else
	echo "$a -eq $b : a不等于b"
fi
布尔运算符
运算符说明举例
!非运算,表达式为 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。
a=10
b=20
if [ $a -lt 100 -a $b -gt 15 ]
then
   echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
   echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
逻辑运算符
运算符说明举例
&&逻辑的 AND[[ $a -lt 100 && $b -gt 100 ]] 返回 false
||逻辑的 OR[[ $a -lt 100 || $b -gt 100 ]] 返回 true
a=10
b=20
if [[ $a -lt 100 && $b -gt 15 ]]
then
   echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
   echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
字符串运算符
运算符说明举例
=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
!=检测两个字符串是否不相等,不相等返回 true。[ $a != $b ] 返回 true。
-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
-n检测字符串长度是否不为 0,不为 0 返回 true。[ -n “$a” ] 返回 true。
$检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。
文件测试运算符
操作符说明举例
-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。

其他检查符:

  • -S: 判断某文件是否 socket。
  • -L: 检测文件是否存在并且是一个符号链接。
file="./bin/haha"
if [ -x ${file} ]
then	
	echo "${file} 可执行"
else
	echo "${file} 不可执行"
fi
Shell echo命令
显示普通字符串
echo "hello world!!!"
显示转义字符
echo "\"hello world!!!\""
显示变量

read命令从标准输入中读取一行,并把输入行的每个字段的值指定给shell变量。

read name
echo "input name :${name}"

read -p "name:" name  #在"name:"命令提示符下输入
read -sp "name:" name #隐藏输入的内容
zhudk@vm1:/expand/zhudk/demo/build$ ./build.sh 
Bobo
input name :Bobo

当执行到read name语句的时候终端会停留在那等待输入。

显示换行/不换行

echo会自动添加换行符。

echo -e "hello \n world!!!"
echo -e "hello\c" #\c不换行
echo -e "world!!!"

-e开启转义。\n换行。\c不换行。

显示结果定向至文件
echo "It is a test" > myfile

>会以命令中的写入内容覆盖原文件内容。如果指定的文件不存在,那么它将会创建一个以指定文件名命名的新文件,并执行写入操作。

>>会将命令中的写入内容附加到原文件内容末尾。如果指定的文件不存在,那么它将会创建一个以指定文件名命名的新文件,并执行写入操作。

显示命令执行结果
echo `date`

注意: 这里使用的是反引号 `, 而不是单引号 '

Shell printf命令

printf命令模仿C程序库李的printf()函数。printf由POSIX标准所定义,因此使用printf的脚本比使用echo移植性好。printf使用引用文本或空格分隔参数,外面可以在printf中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的printf不会象echo自动添加换行符,我们可以手动添加\n

a=100
b="hello"
c=3.14
printf "a=%d b=%s c=%4.4f\n" ${a} ${b} ${c}

%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。

%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。

%-4.2f 指格式化为小数,其中 .2 指保留2位小数。

Shell 日期格式化
格式化选项列表
选项日期指代输出描述输出示例
+%a周一至周五周的英文缩写(如,Mon ,Tue ,Wed )Mon
+%A周一至周五周的完整拼写(如,Monday ,Tuesday ,Wednesday )Monday
+%b月份月份的英文缩写(如,Jan ,Feb ,Mar )Jan
+%B月份月份的完整拼写(如,January ,February ,March )January
+%d某个月的某一日(以数字类型输出)30
+%D日期当前的日期(月/日/年)06/17/2020
+%F日期当前的日期(年-月-日)2020-06-17
+%H小时值(24小时制,以数字类型输出)18
+%I小时值(12小时制,以数字类型输出)6
+%j某年的某一日(001-360,以数字类型输出)135
+%m月份月份(01-12,以数字类型输出)06
+%M分钟值(00-59,以数字类型输出)55
+%N纳秒纳秒值(000000000-999999999,以数字类型输出)123456789
+%S秒钟值(00-59,以数字类型输出)49
+%T时间当前的时间(时:分:秒)11:04:35
+%u当前周(01-07,起始周一,以数字类型输出)03
+%U周数某年的某一周(00-53,起始周日,以数字类型输出)25
+%Y当前完整年份(以数字类型输出)2020
+%Z时区时区缩写(如IST , GMT)IST
mdy=`date +%m-%d-%Y`
echo "Date in format Month-Date-Year"
echo $mdy
#或者
date +"%H:%M:%S"
Shell 休眠

sleep number[suffix]

  1. numeber 是时间值,可以使用正整数或小数。
  2. suffix 是可选后缀(时间单位):
    - s -秒
    - m -分
    - h -时
    - d -天
  3. 如果没有后缀单位,默认秒为单位。
  4. 如果您传递了多个时间参数,总的睡眠时间将等于所有参数的和。
sleep 1d 2h 3m 30s
Shell 流程控制
if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi
for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
Shell 函数
变量作用域

在默认情况下所有变量都定义为全局变量,即使在函数内部声明也是如此。可以使用local关键字在函数内部声明局部变量,该变量只能够在该函数内部使用。

返回值

在函数中,其返回值是执行的最后一个语句的状态。1-255范围内表示失败,其他表示成功。

可以使用return语句指定返回状态,并将其分配给$?

若向要从函数中返回任意实际的值,最简单的选择是将函数的执行结果分配给一个全局变量。

参数传递

与shell传递参数一样。

paramNum=0
method()
{
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "参数总数有 $# 个!"
    paramNum=$#
    echo "作为一个字符串输出所有参数 $* !"
}

method 110 hello 
echo ${paramNum}
经典示例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R13SWqHL-1649840003755)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20220413165158928.png)]

上述cmake项目中,在shell脚本中使用cmake和make命令,免得人工输入命令。

#!/bin/bash
# ./build.sh clean means clean
# ./build.sh means build

#build dir
build_path="./build"

if [[ $# -gt 0 && $1 = "clean" ]]
then
	rm -rf ${build_path}
	echo "clean"
	exit
fi

if [ ! -e ${build_path} ]
then
     	mkdir ${build_path}
     	echo "mkdir ${build_path}"
fi  	
cd ${build_path}
cmake ..
make
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值