测试开发技术网站
博客
设计
设计
开发
Python
测试
unittest
运维
Linux基础应用
CI/CD
CI/CD
数据库
数据库
云计算
云计算
云原生
云原生
爬虫
爬虫
数据分析
数据分析
人工智能
人工智能
登录
注册
Shell----Shell编程快速入门
收藏本文
作者:redrose2100 类别: 日期:2022-07-06 09:38:53 阅读:846 次 消耗积分:0 分
[【原文链接】Shell----Shell编程快速入门](http://devops-dev.com/article/324) [TOC] ![](https://redrose2100.oss-cn-hangzhou.aliyuncs.com/img/c7fef93c-4b13-11ee-81a3-0242ac110004.png) # 一、定义变量 ## 1.1 定义变量的方法 在shell中定义变量使用,如 ```bash $ A=1 $ echo $A 1 $ ``` 注意:在shell中,定义变量的时候,等号前后都不能有空格,如下几种都是错误的 ```bash $ A= 1 -bash: 1: command not found $ A =1 -bash: A: command not found $ A = 1 -bash: A: command not found $ ``` ## 1.2 取消变量 使用unset命令,如下,取消后再打印的时候就显示为空了 ```bash $ A=1 $ echo $A 1 $ unset A $ echo $A $ ``` ## 1.3 声明一个静态变量 使用readonly声明一个静态变量,一经赋值后不能修改也不能取消,只有退出当前登录,下次登录后才取消 ```bash $ readonly B=2 $ echo $B 2 $ unset B -bash: unset: B: cannot unset: readonly variable $ B=3 -bash: B: readonly variable $ ``` ## 1.4 变量定义规则 * 变量名称可以由字母、数字、下划线组成,但是不能以数字开头,环境变量名建议大写 * 等号两侧不能有空格 * 在bash中,变量默认类型都是字符串,无法直接进行数值运算 * 变量的值如果有空格,需要使用双引号或单引号括起来 * 将变量声明为环境变量,需要使用export声明 ## 1.5 实例演示 (1)变量值默认是字符串,不能进行数值运算,如下所示 ```bash $ C=1+1 $ echo $C 1+1 $ ``` (2)变量值中有空格,需要使用引号,如果不使用引号,则会报错,如下所示 ```bash $ D="hello world" $ echo $D hello world $ D=hello world -bash: world: command not found $ ``` (3)如下演示如何使用export声明环境变量,可以发现只有使用export声明为环境变量后,才可以在bash脚本中打印出来,否则在bash脚本中打印的变量E就是一个空 ```bash $ E="hello world" $ echo 'echo $E'>test.sh $ cat test.sh echo $E $ bash test.sh $ export E $ bash test.sh hello world $ ``` # 二、特殊变量 ## 2.1 特殊变量:$n $n,n为数字,n为0-9,$0 代表脚本名称,$1-$9代表第一到第九个参数,9以上的参数需要使用大括号,如${10}表示第10个参数,比如如下,创建test.sh脚本文件,脚本如下,即打印脚本名本身,以及第一个、第二个和第三个参数 ```bash #!/bin/bash echo $0 echo $1 echo $2 echo $3 ``` 用如下的方式执行,可以看出符合我们的预期 ```bash $ bash test.sh hahah 2 100 test.sh hahah 2 100 $ ``` ## 2.2 特殊变量 $# $# 为获取所有输入参数的个数,如下,在test.sh脚本文件中写入如下内容,即打印参数的个数 ```bash #!/bin/bash echo $# ``` 使用如下命令执行,可以看出,当不输入参数时,打印的是0,当输入三个参数时则打印3 ```bash $ bash test.sh 0 $ bash test.sh 111 222 333 3 $ ``` ## 2.3 特殊变量$* $* 作用是获取命令行中所有的参数,$* 把所有的参数看成一个整体,如下test.sh代码即为打印$*的内容 ```bash #!/bin/bash echo $* ``` 执行结果如下,可以看出将执行时输入的三个参数都打印出来了 ```bash $ bash test.sh 111 222 333 111 222 333 $ ``` ## 2.4 特殊变量$@ $@ 作用是这个变量代表命令行中所有的参数,不过$@把每个参数区分对待,如下,在test.sh中编写代码,打印$@ ```bash #!/bin/bash echo $@ ``` 执行结果如下,可以看出此时同样将三个参数都打印出来了 ```bash $ bash test.sh 111 222 333 111 222 333 $ ``` ## 2.5 特殊变量$? $? 作用是获取最近一次执行的命令的返回状态,如果这个变量的值为0,表示上一个命令执行成功,如果这个变量不是0,则证明上个命令执行错误了 如下,当执行ls正确后,$?的值为0,而当输入一个错误的命令时,此时$?的值是127 ```bash $ ls test.sh $ echo $? 0 $ lsss -bash: lsss: command not found $ echo $? 127 $ ``` # 三、运算符 ## 3.1 运算符的基本语法 运算符有以下三种方式: * $((运算式)) * $[运算式] * expr 运算式 这里需要注意的是,当使用expr的时候,运算符前后必须要使用空格 运算符号就是常见的+,-,\\\*,/,%,即加减乘除,其中需要注意的是乘法不是星号,而是带反斜线的* ## 3.2 运算符实例演示 (1) 使用 $((运算式)) 方式,此时运算符前后有没有空格是都可以的,而且此时的乘法就是*号 ```bash $ A=$((2+3)) $ echo $A 5 $ A=$(( 2 + 3 )) $ echo $A 5 $ A=$(( 3+2 )) $ echo $A 5 $ A=$(( 3-2 )) $ echo $A 1 $ A=$((3*2)) $ echo $A 6 $ A=$((3\*2)) -bash: 3\*2: syntax error: invalid arithmetic operator (error token is "\*2") $ A=$((3/2)) $ echo $A 1 $ A=$((3%2)) $ echo $A 1 $ ``` (2) 使用$[运算式]的格式,可以看出,这种方式相对要求比较宽松,运算符前后有没有空格都是可以的 ```bash $ A=$[3+2] $ echo $A 5 $ A=$[ 3+2 ] $ echo $A 5 $ A=$[ 3 + 2 ] $ echo $A 5 $ A=$[ 3 - 2 ] $ echo $A 1 $ A=$[3*2] $ echo $A 6 $ A=$[ 3 /2] $ echo $A 1 $ A=$[ 3% 2] $ echo $A 1 $ ``` (3) expr 表示式,运算符号前后必须有空格,此外乘号需要加反斜线,如下: ```bash $ expr 3+2 3+2 $ expr 3 +2 expr: syntax error $ expr 3+ 2 expr: syntax error $ expr 3 + 2 5 $ expr 3 - 2 1 $ expr 3 * 2 expr: syntax error $ expr 3 \* 2 6 $ expr 3 / 2 1 $ expr 3 % 2 1 $ ``` (4) 混合运算时的用法如下,可以发现使用expr的方式相对要复杂一点,另外两种方式相对比较简单 ```bash $ A=$(((3+2)*4)) $ echo $A 20 $ A=$[(3+2)*4] $ echo $A 20 $ expr `expr 3 + 2 ` \* 4 20 $ ``` # 四、条件判断 ## 4.1 基本语法 [ condition ] 这里需要注意的是condition前后要有一个空格,条件非空即为true,比如 [ xxx ] 返回true,[] 则返回 false ## 4.2 常用判断条件 (1) 两个整数之间比较 * = 字符串比较 * -lt 小于 * -le 小于等于 * -eq 等于 * -gt 大于 * -ge 大于等于 * -ne 不等于 (2) 按照文件权限进行判断 * -r 有读的权限(read) * -w 有写的权限(write) * -x 有执行权限(execute) (3) 按照文件类型进行判断 * -f 文件存在并且是一个常规的文件 * -e 文件存在 * -d 文件存在并是一个目录 ## 4.3 条件判断使用举例 (1) 比较两个数的大小,如下,当返回值为0为true,否则当返回值为1则为false,此外,当放括号与数字之间必须要有空格 ```bash $ [3 -gt 2] -bash: [3: command not found $ [ 3 -gt 2 ] $ echo $? 0 $ [ 3 = 2 ] $ echo $? 1 $ [ 3 -lt 2 ] $ echo $? 1 $ [ 3 -ne 2 ] $ echo $? 0 $ [ 3 -eq 3 ] $ echo $? 0 $ ``` (2) 判断文件类型以及是否存在 ```bash $ mkdir demo $ ls demo test.sh $ [ -f test.sh ] $ echo $? 0 $ [ -d demo ] $ echo $? 0 $ [ -d test.sh ] $ echo $? 1 $ [ -f demo ] $ echo $? 1 $ [ -e test.sh ] $ echo $? 0 $ [ -e demo ] $ echo $? 0 $ [ -e hahahaha ] $ echo $? 1 $ ``` (3) 判断文件权限的条件,如下 ```bash $ ls -l total 4 drwxrwxr-x. 2 honghua honghua 6 Jul 7 13:23 demo -rw-rw-r--. 1 honghua honghua 21 Jul 6 16:52 test.sh $ [ -r test.sh ] $ echo $? 0 $ [ -w demo ] $ echo $? 0 $ [ -x test.sh ] $ echo $? 1 $ [ -x demo ] $ echo $? 0 $ ``` ## 4.4 多条条件判断语句的逻辑关系 * && 表示前一条命令执行成功时,才执行后一条命令,如果前一条命令失败了,则不会执行后一条命令 * || 表示上一条命令执行失败时,才执行下一条命令,如果前一条命令成功了,则不会执行后一套命令 如下,其中test.sh为文件,demo为目录 ```bash $ [ 3 -gt 2 ] && [ -f test.sh ] $ echo $? 0 $ [ -e test.sh ] && [ -x test.sh ] $ echo $? 1 $ [ -d test.sh ] || [ -d demo ] $ echo $? 0 $ ``` # 五、流程控制 ## 5.1 if 语句 ### 5.1.1 if 语句的基本语法格式 (1) 第一种格式 ```bash if[ 条件判断式 ];then 程序 fi ``` (2) 第二种格式 ```bash if[ 条件判断式 ] then 程序 fi ``` 注意事项: * [ 条件判断式 ] 方括号与条件判断表达式之间必须有空格 * if后要有空格 ### 5.1.2 if 语句实例 如下,判断第一个参数是不是1或者2的if判断 ```bash #!/bin/bash if [ $1 -eq 1 ];then echo "first is 1" elif [ $1 -eq 2 ];then echo "first is 2" else echo "first is not 1 and 2" fi ``` 当然then也可以单独放一行,如下 ```bash #!/bin/bash if [ $1 -eq 1 ] then echo "first is 1" elif [ $1 -eq 2 ] then echo "first is 2" else echo "first is not 1 and 2" fi ``` 执行调试结果如下: ```bash $ bash test.sh 1 first is 1 $ bash test.sh 2 first is 2 $ bash test.sh 3 first is not 1 and 2 $ ``` ## 5.2 case语句 ### 5.2.1 case语句的基本语法 ```bash case $变量名 in "值1") 如果变量的值扥估值1,则执行程序1 ;; "值2") 如果变量的值等于值2,则执行程序2 ;; *) 如果变量的值都不是以上的值,则执行此程序 ;; esac ``` 注意事项: (1) case行尾必须为单词 “in”, 每个模式匹配必须以有括号 ")"结束 (2)双分号 ";;"表示命令序列结束,相当于其他语言中的break (3) 最后的 "*)" 表示默认模式,相当于其他语言中的default ### 5.2.2 case语句实例 如下,判断第一个参数是否为1或2 ```bash #!/bin/bash case $1 in 1) echo "num is 1" ;; 2) echo "num is 2" ;; *) echo "num is not 1 and 2" ;; esac ``` 执行结果如下: ```bash $ bash test.sh 1 num is 1 $ bash test.sh 2 num is 2 $ bash test.sh 3 num is not 1 and 2 $ ``` ## 5.3 for 循环 ### 5.3.1 for 循环基本语法 ```bash for (( 初始值;循环控制条件;变量变化 )) do 程序 done ``` ### 5.3.2 for 循环语句实例 (1)如下为计算1-100求和 ```bash #!/bin/bash sum=0 for(( i=1;i<=100;i++ )) do sum=$[$sum+$i] done echo $sum ``` 执行结果如下: ```bash $ bash test.sh 5050 $ ``` (2) 打印所有输入的参数 ```bash #!/bin/bash for i in $* do echo $i done ``` 执行结果如下: ```bash $ bash test.sh 111 222 333 444 555 111 222 333 444 555 $ ``` (3)如下为 $* 和 $@ 的区别 ```bash #!/bin/bash for i in $@ do echo $i done echo ---------------------------- for i in $* do echo $i done echo ---------------------------- echo ---------------------------- for i in "$@" do echo $i done echo ---------------------------- for i in "$*" do echo $i done ``` 执行结果如下,可以看出,在不加引号的情况下,两者循环遍历的时候是相同的,但是当加了双引号后,两者在遍历的时候就不一样了,$*表示的是一个字符串 ```bash $ bash test.sh 111 222 333 111 222 333 ---------------------------- 111 222 333 ---------------------------- ---------------------------- 111 222 333 ---------------------------- 111 222 333 $ ``` ## 5.4 while循环 ### 5.4.1 while循环基本语法 ```bash while[ 条件判断式 ] do 程序 done ``` ### 5.4.2 while循环语句实例 (1)如下为计算1-100之和 ```bash #!/bin/bash i=1 sum=0 while [ $i -le 100 ] do sum=$[$sum + $i ] i=$[$i + 1] done echo $sum ``` 执行结果如下: ```bash $ bash test.sh 5050 $ ``` # 六、read读取控制台输入 ## 6.1 基本语法 ```bash read(选项)(参数) 选项: -p:指定读取值时的提示符 -t:指定读取值时等待的时间(秒) 参数: 变量:指定读取值的变量名 ``` ## 6.2 read读取控制台输入实例 (1) 如下输入用户名的实例 ```bash #!/bin/bash read -p "please input username: " username echo $username ``` 执行结果如下: ```bash $ bash test.sh please input username: redrose2100 redrose2100 $ ``` # 七、函数 ## 7.1 系统函数 ### 7.1.1 basename 获取文件的文件名 (1) 如下为获取文件的文件名 ```bash $ basename demo/test.txt test.txt $ ``` (2) 如下可以通过指定后缀将后缀去掉 ```bash $ basename demo/test.txt .txt test $ ``` ### 7.1.2 dirname获取文件的绝对路径 如下,通过指定文件的绝对路径,从而可以获得文件的绝对路径 ```bash $ dirname /home/honghua/demo/test.txt /home/honghua/demo $ ``` ## 7.2 自定义函数 ### 7.2.1 函数定义基本语法 ```bash [ function ] functionname[()] { Action; [return int;] } ``` 注意点 (1) 必须在调用函数地方之前,先声明函数,shell脚本是逐行运行,不会像其他语言一样先编译 (2) 函数返回值,只能通过$?系统变量获得,可以显示加return语句,如果不加默认将最后一条命令运行结果作为返回值返回 ### 7.2.2 自定义函数实例 如下为求两个数的和,这里需要注意虽然说function可以省略,但是建议写上去,可读性更好,此外函数名后面的小括号也是选填的,同样也是建议写上去,作为代码,可读性也是一个很重要的方面 ```bash #!/bin/bash function sum() { sum=0; sum=$[$1+$2] echo $sum } read -p "please input your param1: " p1 read -p "please input your param2: " p2 sum $p1 $p2 ``` 执行结果如下: ```bash $ bash test.sh please input your param1: 10 please input your param2: 20 30 $ ``` # 八、Shell的工具 ## 8.1 cut cut的作用就是从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出 ### 8.1.1 cut 基本语法 cut [选项参数] filename 其中常用的选项参数如下: * -f 列号,提取第几列 * -d 分隔符,按照指定分析分隔符割裂 ### 8.1.2 cut 实用举例 准备一个demo.txt文件,内容如下: ```bash name age sex zhangsanfeng 100 man quchuji 99 man zhoubotong 101 man ``` (1) 获取第一列 ```bash $ cut -d " " -f 1 demo.txt name zhangsanfeng quchuji zhoubotong $ ``` (2)获取第1,2列 ```bash $ cut -d " " -f 1,2 demo.txt name age zhangsanfeng 100 quchuji 99 zhoubotong 101 $ ``` (3)获取zhangsanfeng的年龄 ```bash $ cat demo.txt |grep zhangsanfeng |cut -d " " -f 2 100 $ ``` (4)取第二列及以后的列 ```bash $ cut -d " " -f 2- demo.txt age sex 100 man 99 man 101 man $ ``` ## 8.2 sed ### 8.2.1 sed 基本语法 sed [选项参数] 'command' filename 其中参数: * -e 直接在指令列模式上进行sed的动作编辑 命令: * a 新增,a的后面可以接字符串,在下一行出现 * d 删除 * s 查找并替换 ### 8.2.2 sed 常用举例 首先准备测试文件demo.txt,内容如下: ```bash name age sex zhangsanfeng 100 man quchuji 99 man zhoubotong 101 man ``` (1)在第二行下面增加 zhangwuji 98 man,操作如下,可以看出如果不使用重定向是不会修改源文件的内容的 ```bash $ sed "2a zhangwuji 98 man" demo.txt name age sex zhangsanfeng 100 man zhangwuji 98 man quchuji 99 man zhoubotong 101 man [honghua@honghua-centos-01 demo]$ cat demo.txt name age sex zhangsanfeng 100 man quchuji 99 man zhoubotong 101 man [honghua@honghua-centos-01 demo]$ ``` (2)删除包含quchuji的行,可以看到,此时也不会修改源文件额内容 ```bash $ sed "/quchuji/d" demo.txt name age sex zhangsanfeng 100 man zhoubotong 101 man [honghua@honghua-centos-01 demo]$ cat demo.txt name age sex zhangsanfeng 100 man quchuji 99 man zhoubotong 101 man [honghua@honghua-centos-01 demo]$ ``` (3) 将每行匹配到的第一个n替换为N,如下,此时不使用g即可 ```bash $ sed "s/n/N/" demo.txt Name age sex zhaNgsanfeng 100 man quchuji 99 maN zhoubotoNg 101 man $ cat demo.txt name age sex zhangsanfeng 100 man quchuji 99 man zhoubotong 101 man $ ``` 如果使用g,则可以将所有匹配内容替换,如下: ```bash $ sed "s/n/N/g" demo.txt Name age sex zhaNgsaNfeNg 100 maN quchuji 99 maN zhoubotoNg 101 maN [honghua@honghua-centos-01 demo]$ cat demo.txt name age sex zhangsanfeng 100 man quchuji 99 man zhoubotong 101 man [honghua@honghua-centos-01 demo]$ ``` (4) 同时执行多条sed命令,如下,删除第二行同时将所有的n替换为N,如下: ```bash $ sed -e "2d" -e "s/n/N/g" demo.txt Name age sex quchuji 99 maN zhoubotoNg 101 maN $ cat demo.txt name age sex zhangsanfeng 100 man quchuji 99 man zhoubotong 101 man $ ``` ## 8.3 awk ### 8.3.1 awk 基本语法 awk [选项参数] 'pattern{action1} pattern2{action2} ...' filename 其中: * pattern:表示awk在数据中查找的内容,就是匹配模式 * action:在找到匹配内容时所执行的一系列命令 选项: * -F 指定输入文件拆分分隔符 * -v 赋值一个用户定义变量 ### 8.3.2 awk 常用实例 (1) 数据准备,将 /etc/password 文件的内容重定向到当前目录下的password文件中,如下: ```bash sudo cat /etc/passwd >> password ``` (2) 使用冒号分隔,取以root开头行的分隔后的第七列 其中以root开头的行尾: ```bash root:x:0:0:root:/root:/bin/bash ``` 执行的命令及结果如下: ```bash $ awk -F : '/^root/ {print $7}' password /bin/bash $ ``` (3) 使用冒号分隔,取以root开头行的分隔后的第七列 ```bash $ awk -F : '/^root/ {print $1,$7}' password root /bin/bash $ ``` (4) 只显示password的第一列和第七列,以逗号分隔,且在所有的行前面添加列名 user,shell,在最后一行增加“admin,/bin/bash” 如下: ```bash $ awk -F : 'BEGIN{print "user,shell"} {print $1,$7} END{print "admin,/bin/bash"}' password user,shell root /bin/bash bin /sbin/nologin daemon /sbin/nologin adm /sbin/nologin lp /sbin/nologin sync /bin/sync shutdown /sbin/shutdown halt /sbin/halt mail /sbin/nologin operator /sbin/nologin games /sbin/nologin ftp /sbin/nologin nobody /sbin/nologin systemd-network /sbin/nologin dbus /sbin/nologin polkitd /sbin/nologin sshd /sbin/nologin postfix /sbin/nologin jiayi /bin/bash jenkins /bin/false gitlab-runner /bin/bash tss /sbin/nologin avahi /sbin/nologin admin,/bin/bash $ ``` (5) 所有的第三列的值加1 ```bash $ awk -F : -v i=1 '{print $3+i}' password 1 2 3 4 5 6 7 8 9 12 13 15 100 193 82 1000 75 90 1001 999 1003 60 71 $ ```
始终坚持开源开放共享精神,同时感谢您的充电鼓励和支持!
版权所有,转载本站文章请注明出处:redrose2100, http://blog.redrose2100.com/article/324
上一篇:
Python----常用模块的用法
下一篇:
Golang基础----Golang中的标识符、关键字和命名规范
搜索
个人成就
出版书籍
《Pytest企业级应用实战》
测试开发技术全栈公众号
测试开发技术全栈公众号
DevOps技术交流微信群
加微信邀请进群
常用网站链接
开源软件洞察
云原生技术栈全景图
Python语言官方文档
Golang官方文档
Docker官方文档
Jenkins中文用户手册
Scrapy官方文档
VUE官方文档
Harbor官方文档
openQA官方文档
云原生开源社区
开源中国
Kubernetes中文文档
Markdown语法官方教程
Kubernetes中文社区
Kubersphere官方文档
BootStrap中文网站
JavaScript中文网
NumPy官方文档
Pandas官方文档
GitLink确实开源网站
数据库排名网站
编程语言排名网站
SEO综合查询网站
数学加减法练习自动生成网站
Kickstart Generator
文章分类
最新文章
最多阅读
特别推荐
×
Close
登录
注册
找回密码
登录邮箱:
登录密码:
图片验证码:
注册邮箱:
注册密码:
邮箱验证码:
发送邮件
注册邮箱:
新的密码:
邮箱验证码:
发送邮件