前言shell 语法
shell 脚本的定义与执行 Shell变量
自定义变量
注意事项 环境变量预设变量脚本变量的特殊用法:"" `` ' () {} 条件测试语句
文件测试字符串测试数字测试复合测试 控制语句
if语句case语句for语句while语句until语句break、continue 函数
函数的定义和调用函数传参函数返回值 前言
本文笔记参考自 千峰教育
b站视频:Linux高级程序设计全套视频教程(通俗易懂)(1P-17P)
定义以开头:#!/bin/bash
#!用来声明脚本由什么 shell 解释,否则使用默认 shell
单个"#"号代表注释当前行
执行:
chmod + x test.sh ./test.sh 增加可执行权限后执行
bash test.sh 直接指定使用 bash 解释 test.sh
、test.sh(source test.sh) 使用当前 shell 读取解释 test.sh
第一种方法需要修改可执行权限
第二三种不需要
三种执行脚本的方式不同点:
./和 bash 执行过程基本一致,后者明确指定 bash 解释器去执行脚本,脚本中#!指定的解释器不起作用。前者首先检测#!,使用#!指定的 shell,如果没有使用默认的 shell
用./和 bash 去执行会在后台启动一个新的 shell 去执行脚本
用.去执行脚本不会启动新的 shell,直接由当前的shell 去解释执行脚本。
示例
demo1.sh 代码
#!/bin/bash# #!用于指定当前脚本文件的shell解释器类型,如果不写,则用默认的shell#shell脚本是shell命令的有序集合,代码的构成就是命令lspwdecho "hello"
运行结果
shell中是没有数据类型的 没有int char…,直接 变量=value
如:i = 50
引用变量
$ 变量名
如:i=$num 把变量 num 的值付给变量 i
显示变量
使用 echo 命令可以显示单个变量取值
如:echo $num
清除变量
使用 unset 命令清除变量
如:unset varname
示例1
demo2.sh代码
#!/bin/bashnum=50i=$numecho $numecho $i unset numecho "***********delete************"echo $num
运行结果
出现如下的报错 (未找到命令)原因是
num=50i=$num
变量与值之间的等号两边出现空格
shell脚本赋值操作时切记不可加空格
变量的其它用法:
read string(类型于scanf)
从键盘输入一个字符串付给变量 string
readonly var=100
定义一个只读变量,只能在定义时初始化,以后不能改变,不能被清除。
export var=300
使用 export 说明的变量,会被导出为环境变量,其它 shell 均可使用
注意:此时必须使用 source 2_var.sh 才可以生效
1_num=10 错误
num_1=20 正确等号两边不能直接接空格符,若变量中本身就包含了空格,则整个字符串都要用双引号、或单引号括起来;双引号内的特殊字符可以保有变量特性,但是单引号内的特殊字符则仅为一般字符。
name=aa bb //错误name="aa bb" //正确echo "$name is me" //输出:aa bb is meecho '$name is me' //输出:$name is me
环境变量 shell 在开始执行时就已经定义了一些和系统的工作环境有关的变量,我们在 shell 中可以直接使用$name 引用
定义:
一般在~/.bashrc 或/etc/profile 文件中(系统自动调用的脚本)使用 export 设置,允许用户后来更改
VARNAME=value export VARNAME
传统上,所有环境变量均为大写
显示环境变量
使用 env 命令可以查看所有的环境变量。
清除环境变量
使用 unset 命令清除环境变量
常见环境变量:
HOME:用于保存注册目录的完全路径名。PATH:用于保存用冒号分隔的目录路径名,shell 将按 PATH 变量中给出的顺序搜索这些目录,找到的第一个与命令名称一致的可执行文件将被执行。 PATH=$HOME/bin:/bin:/usr/bin;export PATH HOSTNAME:主机名SHELL:默认的 shell 命令解析器LOGNAME:此变量保存登录名PWD:当前工作目录的绝对路径名......
在终端下设置的环境变量,仅为临时有效,如果打开另外的终端或者重启等,该环境变量就会消失。如果想设置永久保存的环境变量,可在~/.bashrc 或/etc/profile 文件中 进行添加
VARNAME=value export VARNAME
示例2
demo3.sh代码
#!/bin/bashecho "You are welcome to use bash"echo "Current work dirctory is $PWD"echo "the host name is $HOSTNAME"echo "your home dir $HOME"echo "Your shell is $SHELL"
运行结果
$#:传给 shell 脚本参数的数量$*:传给 shell 脚本参数的内容$1、$2、$3、...、$9:运行脚本时传递给其的参数,用空格隔开$?:命令执行后返回的状态"$?"用于检查上一个命令执行是否正确(在 Linux 中,命令退出状态为 0 表示该命令正确执行,任何非 0 值表示命令出错)$0:当前执行的进程名$$:当前进程的进程号"$$"变量最常见的用途是用作临时文件的名字以保证临时文件不会重复
示例
demo4.sh
#!/bin/bashecho "your shell script name is $0"echo "the params of your input is $*"echo "the num of your input params is $#"echo "the params is $1 $2 $3 $4"lsecho "the cmd state is $?"cd /rootecho "the cmd state is $?"echo "process id is $$"
运行结果
“”(双引号):包含的变量会被解释
‘’(单引号):包含的变量会当做字符串解释
``(数字键 1 左面的反引号):反引号中的内容作为系统命令,并执行其内容,可以替换输出为一个变量等效于$()
```powershell$ echo "today is `date` "today is 2012 年 07 月 29 日星期日 12:55:21 CST 转义字符:同 c 语言 n t r a 等 echo 命令需加-e 转义(命令序列):由子 shell 来完成,不影响当前 shell 中的变量{ 命令序列 }:在当前 shell 中执行,会影响当前变量
示例
demo5.sh代码
#!/bin/bashname=teacherstring1="good moring $name"string2='good moring $name'echo $string1echo $string2echo "today is `date` "echo 'today is `date` 'echo -e "this n istantest"( name=student;echo "1 $name" )echo 1:$name{ name=student; echo "2 $name"; }echo 2:$name
运行结果
条件测试语句 在写shell脚本时,经常遇到的问题就是判断字符串是否相等,可能还要检查文件状态或进
行数字测试,只有这些测试完成才能做下一步动作
test命令:用于测试字符串、文件状态和数字
test命令有两种格式:
test condition 或 [ condition ]
使用方括号时,要注意在条件两边加上空格
shell脚本中的条件测试如下:
文件测试、字符串测试、数字测试、复合测试
测试语句一般与后面讲的条件语句联合使用
按照文件类型
-e 文件名 文件是否存在-s 文件名 是否为非空-b 文件名 块设备文件-c 文件名 字符设备文件-d 文件名 目录文件-f 文件名 普通文件-L 文件名 软链接文件-S 文件名 套接字文件-p 文件名 管道文件
按照文件权限
-r 文件名 可读-w 文件名 可写-x 文件名 可执行
两个文件之间的比较
文件1 -nt 文件2 文件1的修改时间是否比文件2新文件1 -ot 文件2 文件1的修改时间是否比文件2旧文件1 -ef 文件2 两个文件的inode节点号是否一样,用于判断是否是硬链接
示例
demo6.sh代码
$? 返回执行结果 0为正确 非0为错误
#! /bin/bashecho "please input a filename >>> "read FILEtest -e $FILEecho "存在?$?"test -s $FILEecho "非空?$?"[ -r $FILE ]echo "可读?$?"[ -w $FILE ]echo "可写?$?"[ -x $FILE ]echo "可执行?$?"test -b $FILEecho "块设备文件?$?"test -c $FILEecho "字符设备文件?$?"test -d $FILEecho "目录文件?$?"test -f $FILEecho "普通文件?$?"test -L $FILEecho "软链接文件?$?"test -S $FILEecho "套接字文件?$?"test -p $FILEecho "管道文件?$?"
运行结果
s1 = s2 测试两个字符串的内容是否完全一样
s1 != s2 测试两个字符串的内容是否有差异
-z s1 测试s1 字符串的长度是否为0
-n s1 测试s1 字符串的长度是否不为0
a -eq b 测试a 与b 是否相等
a -ne b 测试a 与b 是否不相等
a -gt b 测试a 是否大于b
a -ge b 测试a 是否大于等于b
a -lt b 测试a 是否小于b
a -le b 测试a 是否小于等于b
第一种形式:命令执行控制
&&:
command1 && command2
&&左边命令(command1)执行成功(即返回0)shell才执行&&右边的命令
(command2)
||
command1 || command2
||左边的命令(command1)未执行成功(即返回非0)shell才执行||右边的命令
(command2)
第二种形式:多重条件判定
格式一:if [ 条件1 ]; then执行第一段程序else执行第二段程序fi格式二:if [ 条件1 ]; then执行第一段程序elif [ 条件2 ];then执行第二段程序else执行第三段程序fi
case语句case $变量名称 in“第一个变量内容”)程序段一;;“第二个变量内容”)程序段二;;*)其它程序段exit 1esac
for语句形式一:for (( 初始值; 限制值; 执行步阶 ))do程序段done
形式二:for var in con1 con2 con3 ...do程序段done第一次循环时,$var的内容为con1第二次循环时,$var的内容为con2第三次循环时,$var的内容为con3...当in后面所有的值都赋值完毕并执行命令后,循环结束
while语句while [ condition ]do程序段done
当condition成立的时候进入while循环,直到condition不成立时才退出循环
until语句until [ condition ]do程序段done这种方式与while恰恰相反,当condition成立的时候退出循环,否则继续循环。
break、continue break
break命令允许跳出循环。
break 通常在进行一些处理后退出循环或case 语句
continue
continue 命令类似于break 命令
只有一点重要差别,它不会跳出循环,只是跳过这个循环步骤
有些脚本段间互相重复,如果能只写一次代码块而在任何地方都能引用那就提高了代码的可重用性。
shell允许将一组命令集或语句形成一个可用块,这些块称为shell函数。
定义函数的两种格式:
格式一:函数名(){命令 ...}
格式二:function 函数名(){命令 ...}调用函数的格式为:函数名 param1 param2……
函数传参 使用参数同在一般脚本中使用特殊变量
$1,$2 …$9一样
函数可以使用return 提前结束并带回返回值
return 从函数中返回,用最后状态命令决定返回值。
return 0 无错误返回
return 1 有错误返回