【尚硅谷】Shell脚本从入门到实战_哔哩哔哩_bilibili
本文为上面链接的课程学习记录。
shell脚本需要shell解释器进行执行,shell解释器就是一个应用程序,有多种。
常用/bin/sh和/bin/bash。
$ cat /etc/shells /bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh /usr/bin/tmux
查看系统默认解释器:
$ echo $SHELL /bin/bash
(1)打印hello world
$ touch tmp.sh
#!/bin/bash echo "hello world"
#!/bin/bash 指定脚本解析器。
$ ./tmp.sh hello world
(2)创建一个文件,然后向文件中写入字符串
#!/bin/bash touch new.txt echo "hello world" >> new.txt
">>":输出重定向
$HOME:当前用户的home目录;
$PWD:当前路径
$SHELL:当前命令解析器
$USER:当前用户
(1)基础语法
定义变量:变量=值
注意:等号两边没有空格
$ s=1 $ echo $s 1
撤销变量:unset 变量
$ unset s
申明一个静态变量:readonly 变量名=值
$ readonly b=3 $ b=4 -bash: b: readonly variable
(2)变量定义规则
(1)$n
$n:n为数字,$0代表脚本名称,$1 ~ $9表示第1个到第9个参数,10以上的参数需要使用大括号包含,如${10}。
#!/bin/bash echo "para0:" $0 echo "para1:" $1 echo "para2:" $2 echo "para3:" $3 echo "para4:" $4 echo "para5:" $5 echo "para6:" $6 echo "para7:" $7 echo "para8:" $8 echo "para9:" $9 echo "para10:" ${10}
$ ./tmp.sh 0 1 2 3 4 5 6 7 8 9 para0: ./tmp.sh para1: 0 para2: 1 para3: 2 para4: 3 para5: 4 para6: 5 para7: 6 para8: 7 para9: 8 para10: 9
(2)$#
$#:获取所有输入参数个数,常用于循环。
#!/bin/bash echo "\$#" $#
$ ./tmp.sh 0 1 2 3 4 5 6 7 8 9 10 $# 11
注:第0个参数是脚本的名字。
(3)$*
$*:代表命令行中所有的参数,把所有输入参数看作一个整体。
#!/bin/bash echo "\$*" $*
$ ./tmp.sh 0 1 2 3 4 5 6 7 8 9 10 $* 0 1 2 3 4 5 6 7 8 9 10
(4)$@
$@:也代表命令中的所有参数,但把每个参数区分对待。
#!/bin/bash echo "\$@" $@
$ ./tmp.sh 0 1 2 3 4 5 6 7 8 9 10 $@ 0 1 2 3 4 5 6 7 8 9 10
(5)$?
$?:最后一次执行的命令的返回状态,如果这个变量的值为0,证明上一个命令正确执行;如果为非0(具体值,由命令决定),则证明上一个命令没有正确执行。
$ echo $? 0 $ xxx bash: xxx: command not found... $ echo $? 127
(1)基本语法
语法1:"$((运算符))"或者"[运算式]"
语法2:
注意:expr运算符之间要有空格。乘法是"\*",不是"*"。
(2)举例
$ expr 3+2 3+2 $ expr 3 + 2 5
#!/bin/bash expr 3 + 2 expr 3 - 2 expr 3 \* 2 expr 3 / 2 expr 3 % 2 expr `expr 2 + 3` \* 4 s=$[(2+3)*4] echo $s
$ ./tmp.sh 5 1 6 1 1 20 20
(1)基本语法
[ condition ]:条件非空即为true,[ xxx ]返回true,[]返回false。
注意:condition前后有空格。
(2)常用判断条件
1)两个整数之间的比较
条件 | 说明 | 条件 | 说明 |
---|---|---|---|
= | 字符串比较 | ||
-lt | 小于(less than) | -le | 小于等于(less equal) |
-eq | 等于(equal) | -ne | 不等于(not equal) |
-gt | 大于(greater than) | -ge | 大于等于(greater equal) |
2)按照文件权限进行判断
条件 | 说明 | 条件 | 说明 |
---|---|---|---|
-r | 有读的权限(read) | -w | 有写的权限(write) |
-x | 有执行的权限(execute) |
3)按照文件类型进行判断
条件 | 说明 | 条件 | 说明 |
---|---|---|---|
-f | 文件存在并且是一个常规的文件 | -e | 文件存在(existence) |
-d | 文件存在并是一个目录(directory) |
(3)举例
#!/bin/bash [ 23 -gt 22 ] echo $? [ 23 -lt 22 ] && echo true || echo false [ -w tmp.sh ] && echo true || echo false [ -e tm.txt ] && echo true || echo false
$ ./tmp.sh 0 # 0表示正确执行 false true false
(4)多条件判断
&&表示前一条命令执行成功时,才执行后一条命令,||表示前一条命令执行失败后,才执行下一条命令。
[ 23 -lt 22 ] && echo true || echo false $ ./tmp.sh false
(1)基本语法
if [ 条件判断式 ];then 程序 elif [ 条件判断式 ];then 程序 else 程序 fi
或者
if [ 条件判断式 ] then 程序 fi
注意事项:
#!/bin/bash if [ $1 -eq 1 ];then echo "input 1" elif [ $1 -eq 2 ] then echo "input 2" else echo "input $1" fi
$ ./tmp.sh 1 input 1 $ ./tmp.sh 2 input 2 $ ./tmp.sh 3 input 3
(1)基本语法
case $变量名 in "值1") # 如果变量的值等于值1,则执行程序1 ;; "值2") # 如果变量的值等于值2,则执行程序2 ;; *) # 如果变量的值都不是以上的值,则执行此程序 ;; esac
举例:
#!/bin/bash case $1 in 1) echo "input 1" ;; 2) echo "input 2" ;; *) echo "input $1" ;; esac
$ ./tmp.sh 1 input 1 $ ./tmp.sh 2 input 2 $ ./tmp.sh 3 input 3
(1)基本语法1
for (( 初始值;循环判断条件;变量变化 )) do 程序 done
举例:
#!/bin/bash s=0 for (( i=1;i<=100;i++ )) do s=$[$s+$i] done echo "s = $s"
$ ./tmp.sh s = 5050
(2)基础语法2
for 变量 in 值1 值2 值3 ... do 程序 done
举例:打印所有输入的参数
#!/bin/bash for para in $@ do echo "$para" done
$ ./tmp.sh 1 2 3 4 5 6 1 2 3 4 5 6
#!/bin/bash # "$*"把输入参数当作了一个整体 for para in "$*" do echo "$para" done
$ ./tmp.sh 1 2 3 4 5 6 1 2 3 4 5 6
(1)基本语法
while [ 条件判断式 ] do 程序 done
举例:
#!/bin/bash sum=0 i=1 while [ $i -le 100 ] do sum=$[$sum + $i] i=$[$i + 1] done echo "sum = $sum"
$ ./tmp.sh sum = 5050
(1)基本语法
read (选项)(参数)
选项:
参数:指定读取值的变量名
举例:
#!/bin/bash # 在7秒内输入参数,提示字符串"Enter para during seven seconds: " read -t 7 -p "Enter para during seven seconds: " PARA echo $PARA
$ ./tmp.sh Enter para during seven seconds: haha haha $ ./tmp.sh Enter para during seven seconds:
(1)basename
basename string suffix
功能:删除所有的前缀,包括最后一个"/"字符,然后将字符串显示出来。
选项:suffix为后缀,如果指定了后缀,basename会将pathname或string中的suffix去掉。
举例:
#!/bin/bash pwd1="/home/tmp" pwd2="/home/tmp/hello.txt" basename $pwd1 basename $pwd2 ".txt"
$ ./tmp.sh tmp hello
(2)dirname
dirname 文件绝对路径
功能:从给定的包含绝对路径的文件名中去除文件(非目录部分),然后返回剩下的路径(目录的部分)。
举例:
#!/bin/bash pwd="/home/tmp/hello.txt" dirname $pwd
$ ./tmp.sh /home/tmp
(1)基本语法
# function关键字可选,()也是可选的 [ function ] funcname[()] { Action; [return int;] } funcname
注意事项:
举例:
#!/bin/bash # 求和 function sum() { s=0; s=$[$1+$2] echo $s } read -p "Input para1 : " PARA1 read -p "Input para2 : " PARA2 sum $PARA1 $PARA2
$ ./tmp.sh Input para1 : 10 Input para2 : 20 30
(1)基本用法
cut [选项参数] filename
功能:在文件中负责剪切数据,从文件的每一行剪切字节、字符和字段,并将这些字节、字符和字段输出。
说明:默认分隔符是制表符(\t)
选项参数说明:
举例:
#!/bin/bash if [ $1 -eq 1 ];then # 使用空格进行切割,提取第1列 cut -d " " -f 1 tmp.txt elif [ $1 -eq 2 ];then # 使用空格进行切割,提取第2列 cut -d " " -f 2 tmp.txt elif [ $1 -eq 3 ];then # 使用空格进行切割,提取第2列 cut -d " " -f 2,3 tmp.txt elif [ $1 -eq 4 ];then # 仅切割出字符串"abc" cat tmp.txt | grep abc | cut -d " " -f 2 fi
$ more tmp.txt hello world me haha haha you 123456 abc he $ ./tmp.sh 1 hello haha 123456 $ ./tmp.sh 2 world haha abc $ ./tmp.sh 3 world me haha you abc he $ ./tmp.sh 4 abc
# 选取系统PATH变量名,从第2个“:”开始后的所有路径 $ echo $PATH | cut -d : -f 3-
基本用法:
sed [选项参数] 'command' filename
功能:一种流编辑器,一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容。处理完成后,把缓冲区的内容输出到屏幕,接着处理下一行,不断的重复直到文件末尾。文件内容并没有改变,除非使用重定向存储输出。
选项参数:
命令功能描述:
$ more tmp.txt hello world me haha haha you 123456 abc he # 将like添加到文件的第二行下 $ sed "2a like" tmp.txt hello world me haha haha you like 123456 abc he # 删除包含有he的行 $ sed "/he/d" tmp.txt haha haha you # 将"you"替换为"your" $ sed "s/you/your/g" tmp.txt hello world me haha haha your 123456 abc he # 删除第1行,并将"you"替换为"your" $ sed -e "1d" -e "s/you/your/g" tmp.txt haha haha your 123456 abc he
功能:一个强大的文本分析工具,将文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
基本用法:
awk [选项参数] 'pattern1 {action1} pattern2 {action2} ...' filename
pattern:表示awk在数据中查找的内容,也就是匹配模式。
action:在找到匹配内容时所执行的一系列命令。
选项参数说明:
举例:
$ more tmp.txt Keywords: Status: CLOSED DUPLICATE of bug 1151231 Alias: None Product: Fedora Component: dnf Version: rawhide Hardware: x86_64 OS: Linux Priority: unspecified Severity: high Target Milestone: --- Assignee: Packaging Maintenance Team QA Contact: Fedora Extras Quality Assurance Docs Contact: URL: Whiteboard: Depends On: Blocks: TreeView+ depends on / blocked Reported: 2014-10-17 13:51 UTC by lejeczek Modified: 2014-10-17 13:54 UTC (History) CC List: 7 users (show) Fixed In Version: Doc Type: Bug Fix
# 搜索tmp.txt文件中以Assignee关键字开头的行,并输出该行的第2列(以":"符号进行切割) $ awk -F: '/^Assignee/ {print $2}' tmp.txt Packaging Maintenance Team # 搜索tmp.txt文件中以Assignee关键字开头的行,并输出该行的第1、2列(以":"符号进行切割) $ awk -F: '/^Assignee/ {print $1,$2}' tmp.txt Assignee Packaging Maintenance Team # 文件开头加"user,shell",然后打印,然后文件末尾加"ggg" $ awk 'BEGIN{print "user,shell"} {print} END{print "ggg"}' tmp.txt user,shell Keywords: Status: CLOSED DUPLICATE of bug 1151231 Alias: None Product: Fedora Component: dnf Version: rawhide Hardware: x86_64 OS: Linux Priority: unspecified Severity: high Target Milestone: --- Assignee: Packaging Maintenance Team QA Contact: Fedora Extras Quality Assurance Docs Contact: URL: Whiteboard: Depends On: Blocks: TreeView+ depends on / blocked Reported: 2014-10-17 13:51 UTC by lejeczek Modified: 2014-10-17 13:54 UTC (History) CC List: 7 users (show) Fixed In Version: Doc Type: Bug Fix ggg
awk内置变量:
$ awk -F: '{print "filename:"FILENAME " NR:"NR}' tmp.txt filename:tmp.txt NR:1 filename:tmp.txt NR:2 filename:tmp.txt NR:3 filename:tmp.txt NR:4 filename:tmp.txt NR:5 filename:tmp.txt NR:6 filename:tmp.txt NR:7 filename:tmp.txt NR:8 filename:tmp.txt NR:9 filename:tmp.txt NR:10 filename:tmp.txt NR:11 filename:tmp.txt NR:12 filename:tmp.txt NR:13 filename:tmp.txt NR:14 filename:tmp.txt NR:15 filename:tmp.txt NR:16 filename:tmp.txt NR:17 filename:tmp.txt NR:18 filename:tmp.txt NR:19 filename:tmp.txt NR:20 filename:tmp.txt NR:21 filename:tmp.txt NR:22 filename:tmp.txt NR:23 filename:tmp.txt NR:24 filename:tmp.txt NR:25 # 打印空行所在的行号 $ awk -F: '/^$/ {print "NR:"NR}' tmp.txt NR:20
功能:将文件进行排序,并将排序结果标准输出
基本语法:
sort (选项) (参数)
参数:指定待排序的文件列表
选项说明:
举例:
$ more tmp.txt bb:40:5.4 bd:20:4.2 xz:50:2.3 ae:10:3.5 ss:30:1.6 # 使用":"进行切割,然后按第2列数值大小以相反的顺序进行排序 $ sort -t : -nrk 2 tmp.txt xz:50:2.3 bb:40:5.4 ss:30:1.6 bd:20:4.2 ae:10:3.5