0. shell脚本执行
1. source
通过source命令执行脚本,脚本可无执行权限。
表示在当前bash环境下执行脚本
source xxx.sh
2. .
. 与source等效
. xxx.sh
3. ./
打开一个子shell来读取并执行脚本中的命令
./xxx.sh
- 每个shell脚本有效地运行在父shell(parent shell)的一个子进程里. 这个父shell是指在一个控制终端或在一个xterm窗口中给你命令指示符的进程.shell脚本也可以启动他自已的子进程. 这些子shell(即子进程)使脚本并行地,有效率地地同时运行脚本内的多个子任务.
export 导出环境变量是单向传递,可从父进程传递到子进程,不可从子进程传递到父进程。
1. 特殊字符
1. 替换符
1. 变量替换
- # 注释
—— 注释
# This line is a comment.echo "hello" #test
$ —— 取变量值
str="hello"echo $str//结果输出:hello
${} —— 取变量值
name="IRON"echo I am $nameMAN//结果输出:I am IRONMAN
${v1:-v1} 、${v1:+v2}和$(v1:=v2) —— 三目运算
表示如果变量 var1 为空或已被删除(unset),返回$var2,否则返回var1的值,var1值不变
var1 与var2互斥。
var1=1echo ${var1:-$var2}//结果输出:1
var2=2echo ${var1:-$var2}//结果输出:2
表示如果变量 var1 被定义且不为空,那么返回$var2,否则返回空,var1值不变
var1 与var2共存
var2=2var1=1echo ${var1:-$var2}//结果输出:2
如果变量 var1 为空或已被删除(unset),那么返回 word,并将 var1 的值设置为var2,否则返回var1
var2=2var1=#unset var1echo ${var1:=$var2}echo $var1//结果输出:2 2
- ${#} —— 获取变量长度
str="abc"echo ${#str}//结果输出:3
- ${:}、${::} —— 字符串提取
字符串提取,用法${var:n}。若n为正数,n从0开始,表示在变量var中提取第n个字符到末尾的所有字符。若n为负数,提取字符串最后面n的绝对值个字符,使用时在冒号后面加空格或一个算术表达式或整个num加上括号,如${var: -2}、${var:1−3}或 ${var:(-2)}均表示提取字符串最后两个字符
str="abcdef"echo ${str:0}echo ${str:1}echo ${str:1-3}//结果输出: abcdef bcdef ef
${var:n:m},n是字符串索引起始,m为截取长度
str="abcdef"echo ${str:0:3}//结果输出:abc
- {,}、{..}—— 扩展
echo {1,2,3}.txtecho {1..3}.txt//结果输出:1.txt 2.txt 3.txt1.txt 2.txt 3.txt
- ${//}、${///} —— 模式匹配替换
模式匹配替换。${var/pattern/pattern}表示将var字符串的第一个匹配的pattern替换为另一个pattern。不改变原变量。
str="123abc123abc"echo ${str/123/456}echo ${str//123/456}echo $str//结果输出:456abc123abc456abc456abc123abc123abc
2. 命令替换符
- ``和$()
在反引号 中的内容通常是命令行,程序会优先执行反引号中的内容,并使用运行结果替换掉反引号处的内容(替换命令的输出结果)
$()与``等效
name=`uname -s`#等效name=$(unmae -s)echo $name//结果输出:Linux
2. 字符串符
‘’单引号
单引号括住的内容,被视为常量字符串,引号内的禁止变量扩展,并且单引号字符串中不能出现单引号(对单引号使用转义符后也不行)
“”双引号
两个双引号。双引号包围的内容可以允许变量扩展,可以包含双引号,但需要转义
str="IRON"echo '$str MON'#不允许扩展echo "$str MON"#允许扩展//结果输出:$str MONIRON MON
3. 功能符
1. 语法功能符
分号,语句的分隔符。在shell文件一行写多条语句时,使用分号分割
;; case —— 分隔
name="Mike"case $name in #case后为取值,值后为关键字 in"Jim")echo "case 1:my name is $name";;"Mike")echo "case 1:my name is $name";;*)# *会捕获所有与已知模式不匹配的值echo "case *:unknown name $name";;esac # case与esac配对使用,esac时case反写值,类型if-fi
、>> —— 文件重定向
操作对象是文件
ls >1.txt//等效,标准输出重定向到文件中ls 1>1.txt
& ——描述符重定向
2>&1//表示把 标准错误输出 重定向到 标准输出, 这在控制台下看到的效果 2>&1 和 1>&2 可能是一样的,因为标准输出或标准错误输出的目的地默认都为屏幕。
- <<<
三个小于号,作用就是将后面的内容作为前面命令的标准输入
- ()
- 命令替换时使用
- 用与数组
- {} —— 语句块
- 函数中使用
fun1(){echo "hello world"}fun1//输出结果:hello world
4. 运算符
1. 数据运算符
- +、-、*、/
- % —— 取余
- = —— 赋值
- (()) —— 是shell中算数及赋值运算的扩展
另一个对任何编程语言都很重要的特性是操作数字的能力。遗憾的是,对shell脚本来说,这个处理过程会比较麻 烦。在shell脚本中有两种途径来进行数学运算。
特点:
- 在双括号结构中,所有表达式可以像c语言一样,如:a++,b—等。
- 在双括号结构中,所有变量可以不加入:“$”符号前缀。
- 双括号可以进行逻辑运算,四则运算
- 双括号结构 扩展了for,while,if条件测试运算
- 支持多个表达式运算,各个表达式之间可以使用”,”分开
```c
for 循环
for((i=0;i<10;i++ )) do echo $i done
条件判断
a=3
b=3
if (( $a == $b));then
echo equal
fi
<a name="Xcixz"></a>#### 2. 关系运算符(用于数值比较)- [] —— 用于判断条件是否成立,如[ $a == $b ],注意保留空格- [[]]—— 是对[]的扩展,允许使用<、>、&&、|| 等运算符- ==/-eq —— 判断是否相等- -=/-ne —— 判断是否不相等- -gt —— 判断是否大于- -ge —— 判断是否大于等于- -lt —— 判断是否小于- -le —— 判断是否小于等于<a name="Y28at"></a>#### 3. 逻辑运算符- -a —— 逻辑与- -o —— 逻辑或- -! —— 逻辑非- || —— 1. 用于条件判断时,与[[]]配合使用; 2. 用与命令连接- && —— 同 ||<a name="zzxSK"></a>#### 4. 字符串运算符(字符串比较)- = ,==应该也可以- !=- -z —— 字符串长度是否为0- -n —— 字符串长度是否为非0-n 需注意双引号参考:<br />[https://blog.51cto.com/kunge/1585898](https://blog.51cto.com/kunge/1585898)<a name="s7ysS"></a>#### 5. 文件运算符- -d —— 检查file是否存在并是一个目录- -e —— 检查file是否存在- -f —— 检查file是否存在并是一个文件- -r ——检查file是否存在并可读- -s —— 检查file是否存在并非空- -w —— 检查file是否存在并可写- -x —— 检查file是否存在并可执行- -O —— 检查file是否存在并属当前用户所有- -G —— 检查file是否存在并且默认组与当前用户相同- -nt —— file1 -nt file2 检查file1是否比file2新(修改时间)- -ot —— file1 -ot file2 检查file1是否比file2旧 (修改时间)- -ef —— 两个文件是否为同一个文件,主要看文件设备号与 inode 是否一致<a name="WvYZ8"></a>### 5. 数组<a name="vSCX8"></a>#### 1. 索引数组bash shell中只支持一维数组,Shell 数组用括号来表示,元素用"空格"符号分割开```shellarray=(a b c)echo ${array[0]}echo ${array[1]}echo ${array[2]}//输出结果:a b c
array[0]=aarray[1]=barray[2]=cecho ${array[0]}echo ${array[1]}echo ${array[2]}//输出结果:a b c
获取所有元素
echo ${array[*]}echo ${array[@]}
获取数组元素个数
echo ${#array[*]}echo ${#array[@]}
2. 关联数组
关联数组又称为字典。在使用关联数组之前,需要使用命令 declare -A xxx 对其进行显示声明。
关联数组和索引数组除了索引方式不同,其它完全一致。
declare -A arrayarray["Jack"]=22array["Mike"]=23array["Dog"]=26echo ${array["Jack"]}echo ${array["Mike"]}echo ${array["Dog"]}
6. [] 条件判断
第一个方括号后和第二个方括号前都要加一个空格,否则会报错
判断数值或字符串释放相等应该都可以使用==或=和!=
1. 数值比较
n1 -eq n2 检查n1是否与n2相等n1 -ge n2 检查n1是否大于或等于n2n1 -gt n2 检查n1是否大于n2n1 -le n2 检查n1是否小于或等于n2n1 -lt n2 检查n1是否小于n2n1 -ne n2 检查n1是否不等于n2
2. 字符串比较
str1 = str2 检查str1是否和str2相同str1 != str2 检查str1是否和str2不同str1 < str2 检查str1是否比str2小str1 > str2 检查str1是否比str2大-n str1 检查str1的长度是否非0-z str1 检查str1的长度是否为0
3. 文件判断
-d file 检查file是否存在并是一个目录-e file 检查file是否存在-f file 检查file是否存在并是一个文件-r file 检查file是否存在并可读-s file 检查file是否存在并非空-w file 检查file是否存在并可写-x file 检查file是否存在并可执行-O file 检查file是否存在并属当前用户所有-G file 检查file是否存在并且默认组与当前用户相file1 -nt file2 检查file1是否比file2新file1 -ot file2 检查file1是否比file2旧
7. 特殊变量
$n
传递给脚本或函数的参数,n 是一个数字,表示第几个参数,$0 当前脚本名称。
参数从第10个开始$n无法正常获取到参数,需添加括号${n},为保持格式一致,小于10的也可使用${n}
$
$*、$@
传递给脚本或函数的所有参数,不包括$0
$@ 与 $ 的区别,不被双引号””包含时,都以 $1 $2 … $n 的形式输出所有参数
但是当它们被双引号 “” 包含时,`”$“会将所有的参数作为一个整体,以“$1 $2 … $n”的形式输出所有参数。但是“$@”和$@一样,还是会将各个参数分开,以$1 $2 … $n`的形式输出所有参数
$?
$$
当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID
8. 数据类型
shell 是一门若类型语言,定义变量时不需要指定数据类型,而是根据上下文自动确定。
shell数据类型属于有字符串和整型
字符串可以使用单引号’ ‘,双引号” “。
9. 注意事项
1. shell中变量赋值=前后不允许后空格
TEST_PATH=libpcap #okTEST_PATH= libpcap #ngTEST_PATH =libpcap #ng
3. 在其它目录执行脚本与在脚本目录中执行脚本存在差异
可在脚本中cd到当前路径中再执行
${BASH_SOURCE[0]}与$BASH_SOURCE与$0可能等效
#!/bin/bashset -e#脚本文件名(相对于执行路径(非脚本所在路径))curfile=$0#脚本文件路径(相对于执行路径(非脚本所在路径))curdir=$(dirname $curfile)#脚本文件绝对路径(pwd获取绝对路径)path=$(cd $(dirname $0);pwd)echo curfile:$curfileecho curdir:$curdirecho $path#curfile:./abc/test.sh#curdir:./abc#/home/admi/work/slj/abcfilepath=$(cd "$(dirname "$0")"; pwd)cd $filepaht
3. 遍历参数
for i in $*doecho $idone
5. 为什么要使用 x$1 != x 这种方式来比较呢?想像一下这种方式比较:
if [ -n $1 ] #$1不为空
但如果用户不传参数的时候,$1为空,这时 就会变成 -n ,所以需要加一个辅助字符串来进行比较。
另一种方案时对变量添加双引号 if [ -n “$1” ] 即可
Makefile中条件变量允许为空,shell中不允许
6. 条件/选择语句
if [ condition1 ]thencommand1elif [ condition2 ]command2elsecommandNfi
7. 循环
1. for循环
array=(a b c d e)# 遍历所有元素for i in ${array[*]}doecho $idone//结果输出: a b c d e
# 通过数据元素个数遍历for(( i = 0; i< ${#TARGETS[*]}; i++))doecho "[$i] ${TARGETS[i]}"done
2. while 循环
array=(a b c d e)# 通过数据元素个数遍历while ((i < ${#array[@]}))doecho ${array[i]}((i++))done
# 通过数据元素个数遍历for(( i = 0; i< ${#TARGETS[*]}; i++))doecho "[$i] ${TARGETS[i]}"done
9. 比较关心的功能
basename
为basename指定一个路径,basename命令会删掉所有的前缀包括最后一个slash(‘/’)字符,然后将字符串显示出来。
basename [pathname] [suffix]
basename [string] [suffix]
suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。
file=abc.tar.gzecho $(basename $file .tar.gz)#输出abcpath_file=/home/centos/abc.tar.gzecho $(basename $path_file)#输出abc.tar.gz
字符串拼接
Shell字符串拼接不需要使用任何运算符,将两个字符串并排放在一起即可,简单粗暴。
文件名和后缀
file=abc.pcapecho "filename: ${file%.*}"#输出 abcecho "suffix : ${file##*.}"# 输出pcap
行号
echo $LINENO
与其它shell脚本或makefile变量共享
参考文献
[1] https://blog.csdn.net/K346K346/article/details/51819236
[2] https://yanbin.blog/linux-input-output-redirection/ 重定向
[3] https://www.jianshu.com/p/3e1eaaa3fee8
[4] https://www.runoob.com/linux/linux-shell-array.html
