[TOC]
0x00 快速入门 (1)前言 Shell是什么? 答:Shell(壳)本身是一个用C语言编写的程序也是一个是解释执行的脚本语言即命令解释器
,它在操作系统最外层是用户使用Unix/Linux的桥梁,把用户输入解释给操作系统等待操作系统处理后,将结果输出返回给用户,用户的大部分工作都是通过Shell完成的,还是一个功能强大的编程语言,易编写,易调试,灵活性较强
。
它虽然不是Unix/Linux系统内核的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Unix/Linux系统的关键。
weiyigeek.top-shell位置层次
什么是shell脚本? 答:当Linux命令会语句不在命令行下执行(严格的说命令行执行的语句也是shell脚本),而是通过一个脚本程序文件执行时候,该程序就被称为shell脚本或shell程序;与windows中的bat批处理很类似;用户可以在shell脚本中嵌套命令/变量以及流程控制语句从而形成一个功能强大的shell脚本;
Shell是弱类型语言,既是一种命令语言,又是一种程序设计语言,
作为命令语言
:它交互式地解释和执行用户输入的命令,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序
作为程序设计语言
:它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括变量和流程控制语句
为什么要学Shell编程 答:Shell脚本是实现Linux系统及运维自动化管理的重要且必备的工具,尤其是shell脚本擅长处理村文本类型数据,而linux系统中的配置文件万物皆文件,所有极大的方便了我们使用者进行文件处理;几乎每一个合格的Linux系统管理或者运维工程师都需要学习Shell编程;
脚本的优势:
我们所知道的PHP/java他们主要是用来编写应用程序或是网站主要是实现服务端程序;
shell编程他是一个脚本语言(所见即所得),它不需要执行编译过程之后再执行,他是将编译过程放在执行过程中,
所以执行起来要慢得多。
Shell脚本帮助我们通过简单的脚本或其它方式来自动化、简单化任务的需求。比如,批量增加用户,定时备份脚本,批量记录什么LOG.
Shell有两种执行命令的方式 :
交互式(Interactive):解释执行用户的命令,用户输入一条命令,Shell就解释执行一条。
批处理(Batch):用户事先写一个Shell脚本(Script),其中有很多条命令让Shell一次把这些命令执行完,而不必一条一条地敲命令。
我们需要掌握哪一些基础知识?
命令基础(Linux上常常使用的命令文件管理/字符截取等);
Linux正则表达式以及三剑客(Grep/sed/awk)要熟练;
俗话说工欲善其事必先利其器,vi/vim 或者 nano 必须熟练操作;
(2)Shell 发展史 人物介绍:Steve Bourne
也是贝尔实验室的成员,Dennis Ritchie
和 Ken Thompson
的同事,本来他也就是一个默默无闻的码农。但由于 Ritchie 和 Thompson 玩游戏玩出了个 UNIX,一下子整个贝尔实验室都炸开了锅!
刚开始的时候Thompson 写了个简单的程序作为 UNIX 操作系统的接口界面,有了它人类和操作系统就可以进行交流了,叫 shell(我们在 Linux 打开的那个 Terminal 就是一个 shell), Thompson 还给它起了个名字,叫“Thompson shell”(这哥们可真不低调 )Thompson shell 的功能很简单,用户通过它输入一些指定的命令
利用:它负责解释为需要计算机做的操作并去执行,另外它还能够支持一些简单的脚本,就是把一堆命令写进一个文件里依次执行
缺点:但并没有更高级的例如流程控制,分支,变量,函数之类的东西。
主人公 Bourne 出现了(逮到机会赶紧上 ),也设计了一个 shell,叫“Bourne shell,sh”
(似乎都生怕别人不知道程序是谁写的 )。
这俩好面子的大牛都力挺自己设计的 shell,渐渐的两种 shell 都有了各自的追随者,渐渐的形成了两大阵营(就像如今的 Vim 和 Emacs)。 Thompson 的粉丝觉得简洁才是真理,Bourne 的死忠则认为实用才是王道!就这样撕逼大战一触即发……
weiyigeek.top-SHELL标准转变
那现在打开的 Terminal 到底是什么 shell? 答:事实上现在大多数 Linux 发行版的默认 Shell 叫 Bash
,它的名字是 Bourne-Again SHell 的缩写,这是关于 Bourne shell(sh)的一个双关语:“Bourne again / born again,Bourne再次/重生”,
由 Brian J. Fox
所编写(看还是低调的哥们赢得了最后的胜利 )。
(3)Shell的分类 由于历史原因,shell有很多不同的版本,而且也有很多有相同功能的命令需要我们进行取舍,以至于代码的规范很难统一。
Shell的两种主要语法类型有Bourne和C这两种语法彼此不兼容,由于Linux的标准Shell是Bash!Bash和sh是相互兼容的。Bourne Shell
:也称为B Shell,1979年起Unix就开始使用它主文件名为
[TOC]
0x00 快速入门 (1)前言 Shell是什么? 答:Shell(壳)本身是一个用C语言编写的程序也是一个是解释执行的脚本语言即命令解释器
,它在操作系统最外层是用户使用Unix/Linux的桥梁,把用户输入解释给操作系统等待操作系统处理后,将结果输出返回给用户,用户的大部分工作都是通过Shell完成的,还是一个功能强大的编程语言,易编写,易调试,灵活性较强
。
它虽然不是Unix/Linux系统内核的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Unix/Linux系统的关键。
weiyigeek.top-shell位置层次
什么是shell脚本? 答:当Linux命令会语句不在命令行下执行(严格的说命令行执行的语句也是shell脚本),而是通过一个脚本程序文件执行时候,该程序就被称为shell脚本或shell程序;与windows中的bat批处理很类似;用户可以在shell脚本中嵌套命令/变量以及流程控制语句从而形成一个功能强大的shell脚本;
Shell是弱类型语言,既是一种命令语言,又是一种程序设计语言,
作为命令语言
:它交互式地解释和执行用户输入的命令,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序
作为程序设计语言
:它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括变量和流程控制语句
为什么要学Shell编程 答:Shell脚本是实现Linux系统及运维自动化管理的重要且必备的工具,尤其是shell脚本擅长处理村文本类型数据,而linux系统中的配置文件万物皆文件,所有极大的方便了我们使用者进行文件处理;几乎每一个合格的Linux系统管理或者运维工程师都需要学习Shell编程;
脚本的优势:
我们所知道的PHP/java他们主要是用来编写应用程序或是网站主要是实现服务端程序;
shell编程他是一个脚本语言(所见即所得),它不需要执行编译过程之后再执行,他是将编译过程放在执行过程中,
所以执行起来要慢得多。
Shell脚本帮助我们通过简单的脚本或其它方式来自动化、简单化任务的需求。比如,批量增加用户,定时备份脚本,批量记录什么LOG.
Shell有两种执行命令的方式 :
交互式(Interactive):解释执行用户的命令,用户输入一条命令,Shell就解释执行一条。
批处理(Batch):用户事先写一个Shell脚本(Script),其中有很多条命令让Shell一次把这些命令执行完,而不必一条一条地敲命令。
我们需要掌握哪一些基础知识?
命令基础(Linux上常常使用的命令文件管理/字符截取等);
Linux正则表达式以及三剑客(Grep/sed/awk)要熟练;
俗话说工欲善其事必先利其器,vi/vim 或者 nano 必须熟练操作;
(2)Shell 发展史 人物介绍:Steve Bourne
也是贝尔实验室的成员,Dennis Ritchie
和 Ken Thompson
的同事,本来他也就是一个默默无闻的码农。但由于 Ritchie 和 Thompson 玩游戏玩出了个 UNIX,一下子整个贝尔实验室都炸开了锅!
刚开始的时候Thompson 写了个简单的程序作为 UNIX 操作系统的接口界面,有了它人类和操作系统就可以进行交流了,叫 shell(我们在 Linux 打开的那个 Terminal 就是一个 shell), Thompson 还给它起了个名字,叫“Thompson shell”(这哥们可真不低调 )Thompson shell 的功能很简单,用户通过它输入一些指定的命令
利用:它负责解释为需要计算机做的操作并去执行,另外它还能够支持一些简单的脚本,就是把一堆命令写进一个文件里依次执行
缺点:但并没有更高级的例如流程控制,分支,变量,函数之类的东西。
主人公 Bourne 出现了(逮到机会赶紧上 ),也设计了一个 shell,叫“Bourne shell,sh”
(似乎都生怕别人不知道程序是谁写的 )。
这俩好面子的大牛都力挺自己设计的 shell,渐渐的两种 shell 都有了各自的追随者,渐渐的形成了两大阵营(就像如今的 Vim 和 Emacs)。 Thompson 的粉丝觉得简洁才是真理,Bourne 的死忠则认为实用才是王道!就这样撕逼大战一触即发……
weiyigeek.top-SHELL标准转变
那现在打开的 Terminal 到底是什么 shell? 答:事实上现在大多数 Linux 发行版的默认 Shell 叫 Bash
,它的名字是 Bourne-Again SHell 的缩写,这是关于 Bourne shell(sh)的一个双关语:“Bourne again / born again,Bourne再次/重生”,
由 Brian J. Fox
所编写(看还是低调的哥们赢得了最后的胜利 )。
(3)Shell的分类 由于历史原因,shell有很多不同的版本,而且也有很多有相同功能的命令需要我们进行取舍,以至于代码的规范很难统一。
Shell的两种主要语法类型有Bourne和C这两种语法彼此不兼容,由于Linux的标准Shell是Bash!Bash和sh是相互兼容的。Bourne Shell
:也称为B Shell,1979年起Unix就开始使用它主文件名为1 2 3 4 5 Bourne shell :sh Korn Shell : ksh Bourne Again shell : bash POSIX shell : psh
C Shell
:主要是BSD版的Unix系统中使用,因其语法和C语言相类似而得名:1 2 3 4 c shell : csh TENEX/TOPS C shell : tcsh
weiyigeek.top-shell分类介绍
Linux支持的shell1 2 3 4 5 6 7 echo $SHELL /bin/sh 或者 /usr/bin/sh /bin/bash 或者 /usr/bin/bash /bin/tcsh /bin/csh
0x01 Shell脚本初识 Step1.建立和编写Shell脚本1 2 3 4 5 6 7 vi hello.sh #!/bin/bash #开头必须加上这行注释,脚本才能执行(解释器)建议采用#!/usr/bin/env bash echo "hello world!"
Step2.赋予执行权限运行脚本直接运行1 2 3 4 5 6 7 8 9 10 11 12 13 14 chmod 755 hello.sh ./hello.sh bash hello.sh source hello.sh. hellp.sh sh exit
注意事项 :
0x02 Shell编程之变量 描述:主要学习用户自定义变量、环境变量、语系变量、位置参数变量和预定义变量等变量;变量是PC内存的单元Part,其中修改的值可以改变。
(1)变量类型分类 变量的分类: (变量分类从上到下越来越严格)
1,用户自定义变量
2,环境变量:主要保存的是和系统操作环境相关的数据
3,位置参数变量:主要用来向脚本传递参数或数据,变量名不能自定义,变量名固定的
4,预定义变量:Bash中已经定义好的变量变量名不能自定义,变量作用也是固定的
变量命名规则:
1,和c语言一样,首字母/下划线为首加数字变量名的长度不得超过255个字符
.
2,中间不能有空格,可以使用下划线(_),不能使用标点符号。
3,变量名在有效范围内必须唯一且不能使用bash里的关键字(可用help命令查看保留关键字)
4,在Bash中变量的默认类型都是字符串型
.
5,用户自定义变量小写,系统环境变量大写(注意shell编程格式保持良好的风格)
变量的数据类型:
运行Shell的时候会同时存在三种变量:
局部变量: 在脚本或命令中定义,仅仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量;
环境变量:所有程序包括shell启动的程序都能访问环境变量,有些程序需要环境变量来保证其正常运行,必要时候shell脚本也可以定义环境变量;
shell变量:由shel程序设置的特殊变量,其包括了环境变量已经局部变量,这些变量保证了shell的正常运行;
注意事项:
Linux中默认变量类型都是字符串类型不含有其他类型
,所以对数字计算时要用特殊方法将字符串转变为数字才能计算。
(2)各种括号的作用()、(())、[]、[[]]、{} 描述:为了更好的学习shell中的变量,我们需要先学习各个括号的作用;
1.小括号,圆括号()
命令组:
括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用
。
括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
命令替换:
等同于cmd
shell扫描一遍命令行,发现了$(cmd)
结构,便将$(cmd)
中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。
注意:有些shell不支持如tcsh。
初始化数组:
2.双小括号 (( ))
整数扩展
扩展计算是整数型的计算不支持浮点型((exp))结构扩展并计算一个算术表达式的值
如果表达式的结果为0,那么返回的退出状态码为1,或者 是”假”,而一个非零值的表达式所返回的退出状态码将为0,或者是”true”
若是逻辑判断,表达式exp为真则为1,假则为0。
括号中的运算符、表达式符合C语言运算规则
都可用在$((exp))中,甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制
单纯用 (( )) 也可重定义变量值,比如 a=5; $((a++)) 可将 $a 重定义为6
如:echo $((16#5f)) 结果为95 (16进位转十进制)
,echo $((8#12)) = 10 ,值得学习借鉴;
用于算术运算比较,双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开
只要括号中的表达式符合C语言运算规则,比如可以直接使用for((i=0;i<5;i++)),
如果不使用双括号, 则为for i in $(seq 0 4)或者for i in {0..4}
,再如 if(($i<5)), 如果不使用双括号,则为if [ $i -lt 5 ]
3.单中括号,方括号[]
bash 的内部命令:
[和test是等同的,如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。
if/test结构中的左中括号是调用test的命令标识/右中括号是关闭条件判断的,注意结构中并不是必须有中括号,但是新版的Bash中要求必须这样。
这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。
Test和[]中可用的比较运算符只有==和!=
字符范围:用作正则表达式的一部分,描述一个匹配的字符范围,但是作为test用途的中括号内不能使用正则。
在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号,如a[1]
4.双中括号,方括号[[]]
[[是 bash 程序语言的关键字:
它并不是一个命令,[[ ]] 结构比[ ]结构更加通用。
在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。
支持字符串的模式匹配:
使用=~操作符时甚至支持shell的正则表达式
字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真
[[ ]] 中匹配字符串或通配符,不需要引号
使用[[ … ]]条件判断结构,而不是[ … ],能够防止脚本中的许多逻辑错误。
比如:&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。
比如:可以直接使用if [[ $a != 1 && $a != 2 ]] 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ] 或者 if [ $a -ne 1 -a $a != 2 ]
bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。
实际案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 if [ $i -lt 5 ] if [ $a -ne 1 -a $a != 2 ] if [ $a -ne 1] && [ $a != 2 ] if [[ $a != 1 && $a != 2 ]] for i in $(seq 0 4);do echo $i ;done for i in `seq 0 4`;do echo $i ;done for i in {0..4};do echo $i ;done for ((i=0;i<5;i++));do echo $i ;done PROD_TIPS=N if [[ "${PROD_TIPS} " =~ ^['N' ,'n' ]$ ]]; then echo -e "PROD_TIPS 变量值为 N 或者 n" fi
5.大括号、花括号 {}
常规用法:
大括号拓展:通配(globbing))将对大括号中的文件名做扩展。在大括号中不允许有空白,除非这个空白被引用或转义。
代码块:又被称为内部组结构事实上创建了一个匿名函数 。与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量
。括号内的命令间用分号隔开最后一个也必须有分号
,十分注意:{}的第一个命令和左括号之间必须要有一个空格。
四种特殊的替换结构:(非常重要后面详解 )
四种模式匹配替换结构:
# 是去掉左边(在键盘上#在$之左边)
% 是去掉右边(在键盘上%在$之右边)
#和%中的单一符号是最小匹配,两个相同符号是最大匹配。
四种模式字符串提取和替换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ex1.sh ex2.sh ex1.sh ex2.sh ex3.sh ex4.sh ex1.sh ex2.sh ex3.sh ex4.sh var1=1024 var2="var1" echo ${!var2} ${var:-string} ${var:=string} ${var:+string} ${var:?string} ${var%pattern} ${var%%pattern} ${var#pattern} ${var##pattern} ${var:num} ${var:num1:num2} ${var/pattern/pattern} ${var//pattern/pattern}
这四种模式中都不会改变variable的值,其中只有在pattern中使用了*匹配符号时,%和%%,#和##才有区别。
结构中的pattern支持通配符,*表示零个或多个任意字符,?表示仅与一个任意字符匹配,[…]表示匹配中括号里面的字符,[!…]表示不匹配中括号里面的字符 (基础正则)。
实际案例:
示例1、shell变量替换
1 2 ZBX_MAIN_DB=${ZBX_MAIN_DB:-"mysql"} $echo $ZBX_MAIN_DB
示例2、shell变量匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 var=testcase $echo $var testcase $echo ${var%s*e} testca $echo ${var%%s*e} te $echo ${var#?e} stcase $echo ${var##?e} stcase $echo ${var##*e} $echo ${var##*s} e $echo ${var##test} case var=/home/centos echo $var /home/centos echo ${var:5} /centos echo ${var: -6} centos echo ${var:(-6)} centos echo ${var:1:4} home echo ${var/o/h} /hhme/centos echo ${var//o/h} /hhme/cenths
6.符号$后的括号以及大括号
(1)${a} 变量a的值, 在不引起歧义的情况下可以省略大括号,加花括号是为了帮助解释器识别变量的边界;
(2)$(cmd) 命令替换,和cmd
效果相同,结果为shell命令cmd的输,过某些Shell版本不支持$()形式的命令替换, 如tcsh。
(3)$((expression)) 和exprexpression
效果相同, 计算数学表达式exp的数值, 其中exp只要符合C语言的运算规则即可, 甚至三目运算符和逻辑表达式都可以计算。
实际案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 $ for skill in Ada Coffe Action Java > do > echo "I am good at ${skill} Script" > done yourname="test" greeting="hello," $yourname "!" greeting1="hello,${yourname} !" echo $greeting ;echo greeting1test =linux123456linuxecho ${#test} string="alibaba is a great company" echo ${string:0:5} echo `expr index "$string " o`
补充:单个小括号与单个大括号多条命令执行
(1)单小括号 (cmd1;cmd2;cmd3)
新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。
(2)单大括号 { cmd1;cmd2;cmd3;}
在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开
。
对{}和()而言, 括号中的重定向符只影响该条命令而括号外的重定向符影响到括号中的所有命令。
(3)用户自定义变量 字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似
,识别变量和不识别变量。
符号
作用
‘ ‘
单引号:在单引号中所有的特殊符号,如’$’和’`’(反引号)都没有特殊含义
“ “
双引号:在双引号中特殊符号都没有特殊含义,但是”$”、”`”和”\”是例外,拥有”调用变量的值”、”引用命令”和”转义符”的特殊含义
`id`
插入的命令
可以直接执行
$()
和反引号一样,用来引用系统命令
$
用于调用变量的值,如需要调用变量name的值时,需要用$name的方式得到变量的值。
\
转义符,跟在\之后的特殊符号将失去特殊含义,变味普通字符。如\$将输出”$”符号,而不当作是变量引用
实际案例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 - 任何字符都会原样输出,所以单引号字符串中的变量是无效的; - 单引号字串中不能出现单引号(对单引号使用转义字符后也不不行); str='this is a string $var' - 可以解析变量并且可以出现转义字符 str1="this is a variable $test " 变量名=变量值 echo $变量名test =12346echo "$test " echo $str echo $str1 $echo `id`$echo $(id) uid=0(root) gid=0(root) 组=0(root) aa=$(who) echo "$aa " ${aa} x=123 x="$x " 456 echo $x
weiyigeek.top-单双引号
不同变量类型申明:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 $declare TPATH='Visual C++ -- JAVA' $set -a TPATH $env | grep "TPATH" TPATH=Visual C++ -- JAVA $unset -v TPATH $env | grep "TPATH" declare -a test =0declare -a test [1]=1declare -a test [2]=2$echo ${test[1]} ${test[2]} echo ${test[*]} declare -i test =1024$declare -p test
注意事项:
变量名和等号之间不能有空格
,这可能和你熟悉的所有编程语言都不一样.
用户可以使用env命令和grep命令对其进行查询,已经删除的环境变量再次使用指令查询时,将出现查询不到指定环境变量的输出信息。
(4)环境变量
用户自定义变量:局部变量(只在当前shell中生效,临时
)
系统环境变量:全局变量但是对系统生效的环境变量名和变量作用是固定的一般大写
(当前父shell和所有子shell中生效)
环境变量配置文件: 1 2 3 4 5 6 7 全局配置文件:/etc/profile 用户配置文件:~/.bash_profile 注销时生效的环境变量配置:~/.bash_logout 历史操作:~/.bash_history source .bashrc
系统启动加载Shell环境顺序图:
weiyigeek.top-Shell环境顺序图
设置环境变量的方法:1 2 3 4 declare -x T1="demo" set -a T2="demo" export T3="demo"
查看环境变量:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 env $LOGNAME $UID $Shell $HOME $PWD $PATH $PS1 $PS2 $RANDOM
在PATH环境变量
中Linux中执行可执行文件常用的方法是输入绝对路径,但是如果不输入路径时,系统会在PATH中的路径中寻找该可执行文件,直到找到该指定文件,就执行,但是找不到时就报错。 直接输入文件名就能执行自定义脚本
①将该脚本文件复制到PATH中的任意路径中;
②在PATH中添加该脚本文件的路径;
1 2 3 4 5 echo $PATH /usr/local /sbin:/usr/local /bin:/usr/sbin:/usr/bin:/root/bin PATH="$PATH " :/root/sh
weiyigeek.top-
下面就是设置命令行显示格式对于有强迫症的患者来说是极大的好处,可以随心所欲的设置$PS1变量
;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 set | grep PS1[root@WeiyiGeek ~] \d :代表日期,格式为weekday month date,例如:"Mon Aug 1" \H :完整的主机名称 \h :仅取主机名中的第一个名字 \t :显示时间为24小时格式,如:HH:MM:SS \T :显示时间为12小时格式 \A :显示时间为24小时格式:HH:MM \u :当前用户的账号名称 \v :BASH的版本信息 \w :完整的工作目录名称 \W :利用basename取得工作目录名称,只显示最后一个目录名 \ \$ :提示字符,如果是root用户,提示符为 \[\e[F;Bm\] 其中“F“为字体颜色编号为30-37,“B”为背景颜色,编号为40-47。
weiyigeek.top-Front-backgroudcolor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 PS1='[\[\e[32;40m\]\u@\h \w \t]\$ ' vim .bashrc PS1="[\[\e[32;40m\]\u\[\e[37;40m\]@\h \[\e[31;40m\]\w \[\e[43;40m\]\t\[\e[0m\]]\\$ " source .bashrc /etc/bash.bashrc PS1='${debian_chroot:+($debian_chroot)}\[\e[32;40m\]\u\[\e[37;40m\]@\h:\[\e[34;40m\]\w \[\e[31;40m\]\A\[\e[0m\]\$ ' export PS1="\[\e[37;40m\][\[\e[32;40m\]\u\[\e[37;40m\]@\h \[\e[35;40m\]\w\[\e[2;36m\] `ip addr | grep inet | grep " 255 scope global" |head -1|awk '{print $2 }' | cut -d " /" -f 1`\[\e[1;34m\] \t\[\e[0m\]]\\\\$ " tee -a /etc/bashrc <<'EOF' if [ $UID -eq 0 ];then export PS1="\[\e[37;40m\][\[\e[32;40m\]\u\[\e[33;40m\]@\e[37;40m\]\h \[\e[31;40m\]\w\[\e[36;40m\] `hostname -I|cut -d ' ' -f 1`\[\e[34;40m\] \A\[\e[0m\]]# " else export PS1="\[\e[37;40m\][\[\e[32;40m\]\u\[\e[33;40m\]@\e[37;40m\]\h \[\e[31;40m\]\w\[\e[36;40m\] `hostname -I|cut -d ' ' -f 1`\[\e[34;40m\] \A\[\e[0m\]]\\\\$ " fi EOF
还有一个重要的环境变量就是语序环境变量
,我们在讲解locale命令的时候是有所涉及的,就是$LANG定义系统主语系的变量
;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 echo $LANG zh_CN.UTF-8 locale -a | more LC_ALL : 定义整体语系变量 LANG=en_US.UTF-8 LANG=zh_CN.UTF-8 语系信息放在文件 /etc/sysconfig/i18n 下(`Centos 7以下版本才有`)下次开机以后的系统环境,然后你需要做的就是找到LANG 和 SUPPORTED 这两行,然后将以下内容对应着替换上 LANG="zh_CN.UTF-8" SUPPORTED="ZH_CN.UTF-8:ZH_CN:ZH"
weiyigeek.top-语言环境
如果没有图形界面还非要显示中文的两种方法:
一个是使用第三方工具,且支持中文显示
还有一个使用第三方插件(要在linux字符界面下显示支持中文,需要安装zhcon插件)
1 2 3 rpm -ql zhcon.rpm rpm -ivh zhcon.rpm rpm -e zhcon.rpm
内部字段分隔符变量IFS
描述:internal field separator,IFS 是shell脚本中的一个特殊变量在处理文本数据时很有用。 把单个数据流划分成不同的数据元素的定界符,内部字段分隔符就是用于特定用途的定界符。IFS是存储定界符的环境变量,是shell环境中的默认定界符字符串,默认值为空白字符(换行符、制表符、空格)
实际案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #!/bin/bash data="111,222,333|444,555,666" oldIFS=$IFS IFS='|' for i in $data do echo S:$i done IFS=$oldIFS S:111 S:222 S:333 S:444 S:555 S:666 S:111,222,333 S:444,555,666
IFS被设置为逗号’,’ , shell将逗号解释为一个定界符,因此变量$i在每次迭代中读取由逗号分隔的字符串作为变量值
(5)位置参数变量 主要是向脚本文件中传递脚本运算需要的值,更适合给程序的编写者使用,在我们写可变参数脚本尤其有用的;
主要位置参数变量:1 2 3 4 ${n} : $0 代表脚本本身,$0 ~9代表第一个到底九个参数,如果是9个以上参数需要使用大括号包含 ${10} ${*} :代表命令行中的所有参数,它把所有参数 看成一个整体${@} :代表命令行中的所有参数,它把所有参数 区分对待(划分个体)${#} :代表命令行中所有参数的个数;
实际案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #!/usr/bin/env bash echo "文件名称:" ${0} $0 basename ${0} num1=$1 ;num2=$2 let num3=$num1 +$num2 echo -e "$num1 + $num2 = $num3 \n" for i in `seq $num3 `;do echo "for output: $i " done echo -e "\n" echo "A total of $# Parameters" echo "Every Paraments is:$*" echo -e "The Paraments is:$@ \n" for i in "$*" ;do echo "整体 output:$i " done for j in "$@ " ;do echo "个体 output:$j " done
shift 迁移语句 描述:用于迁移位置变量,将$1~$9依次向左传递;通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理(常见于Linux中各种程序的启动脚本)。 例如当shell程序处理完前九个命令行参数后,可以使用shift 9命令把$10移到$1
;并且位置参数熟料也会随之而变化;
简单说明:1 2 3 4 5 6 7 8 $1 =file1、$2 =file2、$3 =file3、$4 =file4$2 =file2、$3 =file3、$4 =file4 $3 =file3、$4 =file4
实际案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #!/bin/bash while [ $# != 0 ]do echo "prama is $1 ,prama size is $# " shift done ./shift_test.sh a b c prama is a,prama size is 3 prama is b,prama size is 2 prama is c,prama size is 1 echo "参数个数为:$# ,其中:" for i in $(seq 1 $# ) do eval j=\$$i echo "第$i 个参数($" $i "):$j " done shift 3 echo "执行shift 3操作后:" echo "参数个数为:$# ,其中:" for i in $(seq 1 $# ) do eval j=\$$i echo "第$i 个参数($" $i "):$j " done 参数个数为:5,其中: 第1个参数($1 ):a 第2个参数($2 ):b 第3个参数($3 ):c 第4个参数($4 ):d 第5个参数($5 ):e 参数个数为:2,其中: 第1个参数($1 ):d 第2个参数($2 ):e
(6)预定义变量 描述:该变量在发挥着及其重要的角色特别是在Shell编程的时候;
符号
作用
$?
检测上一个命令的返回值,判断是不是执行成功,是则为0不是则不为0
$$
当前 Shell 进程的 pid
$!
:上一个后台进程的 pid 可以使用这两个指令来获取相应的进程 pid
实际案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 echo $?;text=`echo $?`;echo $text 0 $ echo $$ 3672 $ ps aux | grep "3672" root 3672 0.0 0.2 116040 2676 pts/1 Ss 21:28 0:00 -bash date >> /tmp/txt.log & [1] 2795 echo $!2795
weiyigeek.top-当前进程PID
总结事项:
多看书本多操作,很简单的代码。其实真正自己写出来,在运行起来得到结果,也不容易
切勿眼高手低要不得
有时候要求有空格(比如条件判断时),有时候不能有空格(变量赋值时),有时候,单引号有时候又 反引号
(7)变量的间接引用 描述:在Shell高级编程中可以采用eval命令进行变量间的间接引用,eval命令会多次扫描自己的参数(变量)并且运行;些需要进行两次扫描的变量有时候被称为复杂变量。
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 vara=varb varb="ls -lah" eval \$$vara -rwxr-xr-x 2 Administrator 197121 39K 九月 11 2018 git.exe -rwxr-xr-x 1 Administrator 197121 145K 九月 11 2018 git-gui.exe var=varc varc="weiyigeek" eval vard=\$$var echo "Name: ${vard} " x=var var=1024 ${!x}
shell脚本案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #!/bin/bash BLACK='\E[1;30m' RED='\E[1;31m' GREEN='\E[1;32m' YEELOW='\E[1;33m' BLUE='\E[1;34m' PINK='\E[1;35m' CYAN='\E[1;36m' WHITE='\E[1;37m' RES='\E[0m' function demo(){ echo "Last argument is $(eval echo \$$#) " echo "Last argument is $(eval echo $#) " } function colorPrint(){ eval COLOR=\$$1 echo -e "${COLOR} ${2} ${RES} " } function usage(){ echo -e "${RED} Usage:$0 COLOR=[BLACK|RED|YELLOW|BLUE|PINK|CYAN|WHITE] [CONTENT]${RES} " exit 1 } [ 2 -gt $# ] && usage demo $* colorPrint $*
执行结果:1 2 Usage:eval.sh COLOR=[BLACK|RED|YELLOW|BLUE|PINK|CYAN|WHITE] [CONTENT]
weiyigeek.top-eval变量间接引用
(8)变量接收命令 描述:在写shell的时候常常利用执行命令后返回结果作为参考或者进行判断,可以说是非常的常用;
命令的执行结果重定向到变量的几种方式1 2 3 4 5 6 var1=$(command ) var3=$(command 2>&1) var2=`command `
(9)补充变量