Shell 开发的经验总结、从入门到深度教程、收藏!小姐姐一篇教会你写90%的shell脚本!
时间流逝,再回头去看看过去的东西,才会发现哪些东西比较重要,故撰此文,记录我在过去学习和使用shell语言过程中我个人觉得比较重要的部分,做一个小总结和分享。
文章目录
- 1、shell是什么
- 2、变量
- 3、设置环境变量
- 4、位置参数变量
- 5、运算符
- 布尔运算符
- 6、条件判断
- 7、流程控制
- if
- if else
- if else-elif
- case
- for循环
- while
- 无限循环
- until 循环
- case
- break
- 8、字符串
- 单引号
- 双引号
- 拼接字符串
- 获取字符串长度
- 提取子字符串
- 9、echo
- 1.显示普通字符串:
- 2.显示转义字符
- 3.显示变量
- 4.显示换行
- 5.显示不换行
- 6.显示结果定向至文件
- 7.原样输出字符串,不进行转义或取变量(用单引号)
- 8.显示命令执行结果
- 10、数组
- 11、read
- 12、函数
- /dev/null 文件
1、shell是什么
- Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的 界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序
shell执行方式
- 脚本以#!/bin/bash开头
- 脚本需要有可执行权限
[root@master home]# ./1.sh 相对路径执行 hello world [root@master home]# sh 1.sh 可以不给shell脚本x权限,但要用sh去执行 hello world [root@master home]# /home/1.sh 绝对路径执行 hello world
运行shell脚本的三种方式
先来看一个简单的shell脚本:
#!/bin/sh``cd` `/tmp``echo` `"hello,world!"
我们来挨个解释一下脚本的每一行:
第一行:#!后面跟的是解释器的路径(shell本身就是一种解释型语言),解释器的路径是/bin/sh;
第二行:cd命令是切换当前工作目录的命令,tep是linux下根目录的一个子目录;
第三行:echo命令是输出后面所跟的参数
三种执行方法:
第一种:因为shell程序写完之后并没有执行权限,所以该脚本想要执行可以使用chmod命令赋予该脚本可执行的权限,然后再执行。
[root@localhost shell]``# chmod +x echo.sh``[root@localhost shell]``# ./echo,sh``bash``: .``/echo``,sh: 没有那个文件或目录``[root@localhost shell]``# ./echo.sh``hello,world!``[root@localhost shell]``# pwd``/root/shell``[root@localhost shell]``#
第二种:调用解释器使得脚本执行,例如:bash、csh、csh、ash、bsh、ksh等等;
[root@localhost shell]``# sh echo.sh``hello,world!``[root@localhost shell]``# bash echo.sh``hello,world!<br>[root@localhost shell]``# pwd<br><em id="__mceDel">/root/shell</em>
第三种:使用source命令;
root@localhost shell]``# source echo.sh``hello,world!``[root@localhost tmp]``# pdw``bash``: pdw: ``command` `not found``[root@localhost tmp]``# pwd``/tmp
细心的读者可能发现了一个问题:在脚本的第一行有cd命令,这是一个改变工作目录的命令,可是使用第一种和第二种放大执行脚本后当前的工作目录并没有改变(脚本所在的目录是shell文件夹,脚本执行后,使用pwd命令显示出当前的工作目录还是shell),使用第三种方法执行后当前的工作目录就改变了,进入了tmp中。出现这种情况是系统本身执行脚本的方式不同所造成的!
前两种方法执行脚本时系统会创建一个子进程或者说子shell来执行脚本,原来的进程就是父进程或者说父shell,整个过程中父进程会等待子进程执行完毕,然后子进程退出,父进程也退出。cd命令确实被执行了,但是仅仅是在子进程中改变了工作目录,所以脚本执行完后使用pwd显示工作目录并没有改变。而第三种方法执行的shell脚本的话并不创建子进程,就是在原来的进程中执行,所以最后的工作目录改变了。
关于解释型语言和编译型语言
相对于编译型语言存在的,源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码进行解释运行。比如Python/JavaScript / Perl /Shell等都是解释型语言。
解释型语言:程序不需要编译,程序在运行时才翻译成机器语言,每执 行一次都要翻译一次。因此效率比较低。比如Basic语言,专门有一个解释器能够直接执行Basic程 序,每个语句都是执行的时候才翻译。(在运行程序的时候才翻译,专门有一个解释器去进行翻译,每个语句都是执行的时候才翻译。效率比较低,依赖解释器,跨 平台性好.)
2、变量
Linux Shell中的变量分为,系统变量和用户自定义变量
系统变量:
- HOME、HOME、HOME、PWD、SHELL、SHELL、SHELL、USER等等
- 显示当前shell中所有变量 set
自定义变量
定义变量的规则
- 变量名称可以由字母、数字和下划线组成,但是不能以数字开头。
- 等号两侧不能有空格
[root@master etc]# a = 100 -bash: a: 未找到命令 [root@master etc]# a= 100 -bash: a: 只读变量 -bash: 100: 未找到命令
- 变量名称一般习惯为大写
将命令的返回值赋给变量
A=`ls -la` 反引号,运行里面的命令,并把结果返回给变量A
A=$(ls -la) 等价于反引号
c=`ls -alh` #会将结果返回 或者 c=$(ls -alh)
[root@master etc]# a=1 定义变量 [root@master etc]# echo $a 1 [root@master etc]# unset a 撤回变量 [root@master etc]# echo $a
静态变量 不能unset. 用readonly定义
[root@master etc]# readonly a=100 [root@master etc]# echo $a 100 [root@master etc]# unset a -bash: unset: a: 无法反设定: 只读 variable
把变量提升为全局环境变量 供其他shell程序使用
- export
**变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,**比如下面这种情况:
your_name="qinjx" echo $your_name echo ${your_name}
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
for skill in Ada Coffe Action Java; doecho "I am good at ${skill}Script" done
3、设置环境变量
- export 变量名=变量值 (功能描述:将shell变量输出为环境变量)
- source 配置文件 (功能描述:让修改后的配置信息立即生效)
- echo $变量名 (功能描述:查询环境变量的值)
4、位置参数变量
当我们执行一个shell脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量
- 比如 : ./myshell.sh 100 200 , 这个就是一个执行shell的命令行,可以在myshell 脚本中获取到参数信息
基本语法:
$n
$0代表本身。
$1-$9代表1-9个参数 十以上的参数需要用{}包含 如{100}
$* 所有参数
$@ 把每个参数区分对待
$# 参数个数
echo "$0 $1 $2" echo "$*" echo "$@" echo "$#"
预定义变量
就是shell设计者事先已经定义好的变量,可以直接在shell脚本中使用
$$ 当前进程的进程号PID
$! 后台运行的最后一个进程的进程号PID
$? 最后一次执行的命令返回的状态 如果这个变量的值为0 证明上一个命令执行正确。
echo "当前进程号=$$" #后台方式运行 ./2.sh & #&代表后台运行 echo "最后进程号=$!" echo "最后执行状态=$?"
5、运算符
- “((运算式))”或“((运算式))”或“((运算式))”或“[运算式]”
NUM=$(((2+3)*4)) echo "num=$NUM"NUM2=$[(2+3)*4] echo "num2=$NUM2"
- expr m + n 注意expr运算符间要有空格 . 反引号 空格
TEMP=`expr 2 + 3` NUM3=`expr $TEMP \* 4` echo "num3=$NUM3"
- expr m - n
- expr *, /, % 乘,除,取余
求两个参数的和
SUM=$[$1+$2] echo "SUM=$SUM"
布尔运算符
下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:
运算符 说明 举例 ! 非运算,表达式为 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。 if [ $a != $b ] thenecho "$a != $b : a 不等于 b" elseecho "$a == $b: a 等于 b" fi if [ $a -lt 100 -a $b -gt 15 ] thenecho "$a 小于 100 且 $b 大于 15 : 返回 true" elseecho "$a 小于 100 且 $b 大于 15 : 返回 false" fi if [ $a -lt 100 -o $b -gt 100 ] thenecho "$a 小于 100 或 $b 大于 100 : 返回 true" elseecho "$a 小于 100 或 $b 大于 100 : 返回 false" fi if [ $a -lt 5 -o $b -gt 100 ] thenecho "$a 小于 5 或 $b 大于 100 : 返回 true" elseecho "$a 小于 5 或 $b 大于 100 : 返回 false" fi
6、条件判断
语法 : [ 条件表达式 ] # if test $[num1] -eq $[num2] []等价于test
整数之间的判断
-eq 相等 -ne 不等 -gt 大于 -lt 小于 -ge 大于等于 -le 小于等于
字符串之间的判断 =
-z 是否为空字符串 字符串长度为0,就成立 -n 是否为非空字符串 只要字符串非空,就是成立 string1 = string2 是否相等 --等号两边要有空格 string1 != string2 不等 ! 结果取反
文件权限判断
-r 当前用户对其是否可读 -w 当前用户对其是否可写 -x 当前用户对其是否可执行 -u 是否有suid -g 是否sgid -k 是否有t位
文件类型判断
-e 是否存在 不管是文件还是目录,只要存在,条件就成立 -f 是否为普通文件 -d 是否为目录 -S socket -p pipe -c character -b block -L 软link
文件内容判断
-s 是否为非空文件 ! -s 表示空文件
实例
if [ "ok" = "ok" ] #都要加空格 thenecho "equal" fiif [ -e /root/1.txt ] thenecho "存在" fi
7、流程控制
if
if condition thencommand1 command2...commandN fi
if else
if condition thencommand1 command2...commandN elsecommand fi
if else-elif
if condition1 thencommand1 elif condition2 then command2 elsecommandN fi
[ 条件判断式 ],中括号和条件判断式之间必须有空格
case
case 值 in 模式1)command1command2...commandN;; 模式2)command1command2...commandN;; esac
echo '输入 1 到 4 之间的数字:' echo '你输入的数字为:' read aNum case $aNum in1) echo '你选择了 1';;2) echo '你选择了 2';;3) echo '你选择了 3';;4) echo '你选择了 4';;*) echo '你没有输入 1 到 4 之间的数字';; esac
for循环
for var in item1 item2 ... itemN docommand1command2...commandN donefor loop in 1 2 3 4 5 doecho "The value is: $loop" done
while
while condition docommand done
无限循环
while : docommand done 或者while true docommand done 或者for (( ; ; ))
until 循环
until 循环执行一系列命令直至条件为 true 时停止。
until condition docommand done
#!/bin/basha=0until [ ! $a -lt 10 ] doecho $aa=`expr $a + 1` done
case
break
8、字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。
单引号
str='this is a string'
单引号字符串的限制:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
双引号
your_name='runoob' str="Hello, I know you are \"$your_name\"! \n" echo -e $str
输出结果为:
Hello, I know you are "runoob"!
双引号的优点:
- 双引号里可以有变量
- 双引号里可以出现转义字符
拼接字符串
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !' #可以作为字符串拼接
greeting_3='hello, ${your_name} !' #原样输出
echo $greeting_2 $greeting_3
输出结果为:
hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !
获取字符串长度
string="abcd"
echo ${#string} #输出 4
提取子字符串
以下实例从字符串第 2 个字符开始截取 4 个字符:
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo
9、echo
1.显示普通字符串:
echo "It is a test"
这里的双引号完全可以省略,以下命令与上面实例效果一致:
echo It is a test
2.显示转义字符
echo "\"It is a test\""
结果将是:
"It is a test"
同样,双引号也可以省略
3.显示变量
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
#!/bin/sh read name echo "$name It is a test"
4.显示换行
echo -e "OK! \n" # -e 开启转义 echo "It is a test"
输出结果:
OK!It is a test
5.显示不换行
#!/bin/sh echo -e "OK! \c" # -e 开启转义 \c 不换行 echo "It is a test"
输出结果:
OK! It is a test
6.显示结果定向至文件
echo "It is a test" > myfile
7.原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'
输出结果:
$name\"
8.显示命令执行结果
echo `date`
注意: 这里使用的是反引号 `, 而不是单引号 '。
10、数组
定义数组
array_name=(value1 value2 ... valuen)
array_name[0]=value0 array_name[1]=value1 array_name[2]=value2
读取数组
${array_name[index]}#!/bin/bash my_array=(A B "C" D) echo "第一个元素为: ${my_array[0]}" echo "第二个元素为: ${my_array[1]}" echo "第三个元素为: ${my_array[2]}" echo "第四个元素为: ${my_array[3]}"
获取数组中的所有元素、获取数组的长度 使用@ 或 * 可以获取数组中的所有元素
echo "数组的元素为: ${my_array[*]}" echo "数组的元素为: ${my_array[@]}" echo "数组元素个数为: ${#my_array[*]}" echo "数组元素个数为: ${#my_array[@]}"
11、read
read [-rs] [-a ARRAY] [-d delim] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [var_name1 var_name2 …]
选项说明: -a:将分裂后的字段依次存储到指定的数组中,存储的起始位置从数组的index=0开始。 -d:指定读取行的结束符号。默认结束符号为换行符。 -n:限制读取N个字符就自动结束读取,如果没有读满N个字符就按下回车或遇到换行符,则也会结束读取。 -N:严格要求读满N个字符才自动结束读取,即使中途按下了回车或遇到了换行符也不结束。其中换行符或回车算一个字符。 -p:给出提示符。默认不支持"\n"换行,要换行需要特殊处理,见下文示例。例如,"-p 请输入密码:" -r:禁止反斜线的转义功能。这意味着"\"会变成文本的一部分。 -s:静默模式。输入的内容不会回显在屏幕上。 -t:给出超时时间,在达到超时时间时,read退出并返回错误。也就是说不会读取任何内容,即使已经输入了一部分。 -u:从给定文件描述符(fd=N)中读取数据。
#!/bin/bash read -p "请输入一个数num=" NUM echo "你输入的值是:$NUMN"
12、函数
系统函数
basename 获取文件名
#!/bin/bash basename /home/aaa/test.txt basename /home/aaa/test.txt .txt 去除后缀
dirname 获取文件的路径 去除文件名
dirname /home/zz/dd/cc/1.txt
自定义函数
[ function ] funname [()]{action;[return int;]}
- 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
- 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
!/bin/bash # author:菜鸟教程 # url:www.runoob.comdemoFun(){echo "这是我的第一个 shell 函数!" } echo "-----函数开始执行-----" demoFun echo "-----函数执行完毕-----"funWithReturn(){echo "这个函数会对输入的两个数字进行相加运算..."echo "输入第一个数字: "read aNumecho "输入第二个数字: "read anotherNumecho "两个数字分别为 $aNum 和 $anotherNum !"return $(($aNum+$anotherNum)) } funWithReturn echo "输入的两个数字之和为 $? !"
Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…
带参数的函数示例:
#!/bin/bash # author:菜鸟教程 # url:www.runoob.comfunWithParam(){echo "第一个参数为 $1 !"echo "第二个参数为 $2 !"echo "第十个参数为 $10 !"echo "第十个参数为 ${10} !"echo "第十一个参数为 ${11} !"echo "参数总数有 $# 个!"echo "作为一个字符串输出所有参数 $* !" } funWithParam 1 2 3 4 5 6 7 8 9 34 73
13、重定向
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
- 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
- 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
- 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
Shell 开发的经验总结、从入门到深度教程、收藏!小姐姐一篇教会你写90%的shell脚本!相关推荐
- 收藏!一篇教会你写90%的shell脚本
在公司项目的开发过程中,总会存在需要编写shell脚本去处理一个业务的场景, 看完这边文章应该就可以独立完成大部分脚本得编写! shell脚本? 在说什么是shell脚本之前,先说说什么是shell. ...
- shell 获取家目录_一篇教会你写90%的shell脚本
shell是外壳的意思,就是操作系统的外壳.我们可以通过shell命令来操作和控制操作系统,比如Linux中的Shell命令就包括ls.cd.pwd等等.总结来说,Shell是一个命令解释器,它通过接 ...
- linux shell 宏定义_一篇教会你写90%的shell脚本
shell是外壳的意思,就是操作系统的外壳.我们可以通过shell命令来操作和控制操作系统,比如Linux中的Shell命令就包括ls.cd.pwd等等.总结来说,Shell是一个命令解释器,它通过接 ...
- 这100个shell脚本案例,你都知道吗?一篇教会你写90%的shell脚本
shell 是一个应用程序,它连接了用户和 Linux 内核,让用户能够更加高效.安全.低成本地使用 Linux 内核,这就是 Shell 的本质. shell脚本就是由Shell命令组成的执行文件, ...
- 一文教会你写90%的shell脚本!
来自:匠心Java 大家好,我是老C,很开心和大家见面~ 在公司项目的开发过程中,总会有需要编写shell脚本去处理一个业务的时候,也有的小伙伴总会问我关于shell脚本的一些知识,在这里博主整理了一 ...
- powershell 开发入门_详谈Ubuntu PowerShell(小白入门必看教程)
早在去年八月份PowerShell就开始开源跨平台了,但是一直没有去尝试,叫做PowerShell Core. 这里打算简单介绍一下如何安装和简单使用,为还不知道PowerShell Core on ...
- 【微信小程序开发•系列文章一】入门
本系统文章主要有以下几篇: <[微信小程序开发•系列文章一]入门> <[微信小程序开发•系列文章二]视图层> <[微信小程序开发•系列文章三]数据层> <[微 ...
- 微信小程序开发 项目经验总结02
微信小程序开发 项目经验总结02 总结 button设置登录授权 小程序:授权.登录.session_key.unionId 做网络请求: wx.request({url: '***',success ...
- 2020年末知识大总结:Java程序员转Android开发必读经验一份,嵌入式开发入门教程
Android是主流智能手机的操作系统,Java是一种开发语言,两者没有好坏优劣之分,只是两种职业岗位的选择.学安卓从事移动互联方向开发,学Java从事软件.网站开发.而安卓上的应用大多是Java编写 ...
最新文章
- 看AI如何改变医疗影像学
- 算法------最接近的三数之和
- 一个抓取网站图片并提供批量下载功能的Chrome扩展
- P5217 贫穷 平衡树
- 终端terminal的颜色配置
- Shell离线脚本安装mysql、更新密码
- Android小知识10则(上)(2018.8重编版)
- mysql支持多语言_多种语言连接MySQL-Go语言中文社区
- 使用 logback + slf4j 进行日志记录
- Swift - 使用下划线(_)来分隔数值中的数字
- mac如何判断本机有没有gpu_属牛人:属牛如何判断一段感情有没有未来
- Fuzz:插桩技术入门
- java中map是不是有序_Map中有序存储
- retrofit简单的网络请求
- ArrayList类的基本使用,完成案例随机不重复点名的程序
- PTA - 数据库合集4
- 《高效能青少年的七个习惯》读后感作文3700字
- 《人人都是项目经理》之立项与启动(二)
- 用淘汰的笔记本搭建服务器,使用神卓互联来做内网穿透不要太香
- 新中国成立以来的历次暴富机会