目录
1.shell脚本的执行方法 2.shell的变量类型 3.shell特殊变量
4.变量子串的常用操作 5.批量修改文件名实践 6.变量替换
7.在shell中计算字符串长度的方法 8.变量的数值计算:(()) 的用法
9. 变量的数值计算:let的用法 10.变量的数值计算:exPR的用法
11.变量的数值计算:bc的用法 12.条件测试的多种方法
13.字符串测试操作符 14.整数二元比较操作符
15.逻辑操作符 16.利用shell知识制作单级及多级菜单
17.case结构条件语句 18. 当型循环和直到型循环
19.for循环
待续。。。
当shell脚本以非交互的方式运行时,它会先查找环境变量ENV,该变量指定了一个环境文件(通常是.bashrc),然后从该环境变量文件开始执行,当读取了ENV文件后,SHELL才开始执行shell脚本中的内容。
shell脚本的执行通常可以采用以下三种方法:
bash script-name 或者 sh script-namepath/script-name 或者 ./script-name(当前路径下执行)source script-name 或 . script-name(注意符号“.”与 script-name之间有空格)第一种方法是脚本文件本身没有可执行权限时,通常使用的方法;
第二种方法需要先将脚本文件的权限改为可执行,然后通过脚本路径就可以直接执行;
第三中方法是在当前shell环境中直接执行,而不是新创建一个子shell,当我们需要在一个脚本中使用另一个脚本中的变量的时候就使用第三种方法,例如创建如下脚本,其中定义了chars变量:
通过上面三种方法执行:
可以看出方法1,2执行脚本是系统会自动新创建一个子shell,执行之后,其变量不会在当前shell有效,而第三种方法是告诉系统让这个脚本直接在当前shell执行,显然其定义的变量chars在当前shell中也是有效的,所以需要在某个脚本中使用另外一个脚本中的变量时,需要使用第3中方法执行脚本。
shell中的变量分为环境变量和全局变量
环境变量也称为全局变量,可以在创建他们的shell及其派生的任意子进程shell中使用。局部变量只能使用在创建它们的shell函数或脚本中使用。
环境变量用于定义Shell的运行环境,保证shell命令的正确执行,shell通过环境变量来确定登录用户名,命令路径,终端类型,登录目录。环境变量可以在命令行中设置,但用户退出时这些变量值也会丢失,因此最好在用户家目录下的.bash_ptofile文件会全局配置/etc/profile文件或者/etc/profile.d中定义,将环境变量放入profile中,每次用户登录,这些变量值都将被初始化。
传统上,所有环境变量均为大写。环境变量用于用户进程前,必须用export命令导出。
有一些环境变量,比如HOME,PATH,SHELL,UID,USER等在用户登录之前就已经被/bin/login程序设置了,通常环境变量的定义并保存在用户的家目录下的./bash_profile文件中。
已经定义的变量可以用unset在取消定义。
本地变量定义的三种方式:
var_name=value
var_name='value'
var_name="value"
下面看看这三种方式的区别
第一种方法是直接定义变量内容,但是内容必须连续,中间不能有空格字符;
接着看下面:
第二种方法通过单引号定义变量,只会原样输出字符串内容,而不会对字符串中的变量和特殊字符进行解析,适合定义单纯字符显示;
第一种和第三种,输出时,会对内容进行解析,输出解析后的内容,有于第一种方法不能定义不连续的变量,所以通常在需要解析的时候都加上双引号,而很少使用第一种方法,第一种方法一般仅仅用来定义连续的数字或者路径。
位置变量
进程状态变量
编号 | 表达式 | 说明 |
1 | ${#string} | 返回$string的长度 |
2 | ${string:position} | 在$string中,从位置position之后开始提取子串 |
3 | ${string:position:length} | 在 |
4 | ${string#substring} | 从变量 |
5 | ${string##substring} | 从变量 |
6 | ${string%substring} | 从变量 |
7 | ${string%%substring} | 从变量 |
8 | ${string/substring/replace} | 使用 |
9 | ${string//substring/replace} | 使用 |
10 | ${string/#substring/replace} | 如果 |
11 | ${string/%substring/replace} | 如果 |
举例说明如下:
例如有下面的文件:
现在想要将后缀前部改为大写JPG:
方法一:
#!/bin/bashfor obj in $(ls *.jpg)do mv ${obj} $(echo ${obj/%jpg/JPG})done方法二:
rename 's/jpg$/JPG/' *.jpg
6.变量替换 返回目录
运算符号 | 作用 |
${value:-Word} | 如果变量名存在且非null,返回变量值;否则,返回word字符串 用途:如果变量未定义,则返回默认值 |
${value:=word} | 如果变量名存在且非null,返回变量值;否则,设置这个变量值为word 用途:如果变量未定义,,则设置变量为默认值,并返回默认值 |
${value:?"not defined"} | 如果变量名存在且非null,返回变量值;否则显示“not defined”,并退出当前命令或脚本。 用途:用于捕捉由于变量未定义而导致的错误,并退出程序。 |
${value:+word} | 如果变量名存在且非null,返回word,否则返回null。 用途:测试变量是否存在。 |
示例如下:
建立一个字符串:
注意:使用 wc -m 的方法会计算换行符,因为echo会在输出完字符串之后自动加上一个换行符,使用echo -n 会去掉换行符:
比较上面三种方法的效率:
time :
获取一个程序的执行时间,可以获取到实际运行时间以及程序在用户态和内核态分别的时间,大部分的性能测试,可能只需要关注实际(real)时间
看到上面三种获取字符串长度的速度相差几十倍到上百倍,一般调用外部命令处理,与内置功能性能相差很大。所以在shell编程,尽量使用内置操作或函数完成。
(1) (())用法:(此法很常用,且效率高)
用于执行的整数运算,支持的运算符与C语言中的基本一致,除了特别注意 "**" 在 (()) 中表示幂运算,而C语言不支持,如 ((2**3)) 结果是 8.
示例:
注意:1)**表示幂运算
2)上面涉及的变量元素必须为整型,不能是小数和字符,涉及小数的后面使用 bc 可以实现。
(()) 内部的变量可以不用加
各种shell运算的脚本例子:
实践:用shell脚本编写一个实现加,减,乘,除的计算器:
与 ((表达式)) 功能一致,但是没有 (()) 的计算效率高,所以常用 (()),而不去使用let.
expr命令一般用于整数计算,但也可用于字符串,用来求表达式变量的值,同时expr也是一个手工命令计算器。
expr 的语法不是很好,所以不常用,这里标记,保证看到别人使用的时候,自己能够看懂。
下面介绍expr比较好用两个技巧
1)检查某个文件是否是某一类型或扩展名:
2)判断一个变量是否是整数:
写出判断一个输入是否为整数的脚本:
bc支持科学计算
使用shell编写输出杨辉三角的脚本:
#!/bin/bashexport%20LANG="zh_CN.GB18030"#本文内容来自《老男孩linux运维实战培训中心》shell%20编程部分学生练习资料#如果脚本后面没有参数,提示输入一个参数if%20(%20test%20-z%20$1%20);then%20%20%20%20read%20-p%20"Input%20max%20int%20lines:"%20MAX%20else%20%20%20%20MAX=$1fi#判断参数的合法性#将参数中的数字全部替换为空,然后判断替换后的内容是否为空#若不为空,表明参数中含有非数字的其他非数字内容,则不合法#“[%20]”的功能与test一致,可以%20man%20test%20查看[%20-n%20"$(echo%20${MAX}|sed%20's/[0-9]//g')"%20]%20&&%20/echo%20"The%20number%20you%20input%20must%20be%20int(1-9)"%20&&%20exit%201#将输入限制在小于10[%20!%20${MAX}%20-lt%2010%20]%20&&%20/echo%20"The%20number%20you%20input%20must%20be%20int(1-9)"%20&&%20exit%201#starta[0]=1for%20((i=0;i<MAX;i++))do%20%20%20%20for%20((j=$i;j>0;j--))%20%20%20%20do%20%20%20%20%20%20%20%20((a[$j]+=a[$j-1]))%20%20%20%20done%20%20%20%20for%20((j=0;j<=MAX-i;j++))%20%20%20%20do%20%20%20%20%20%20%20%20if%20((MAX<=6));then%20%20%20%20%20%20%20%20%20%20%20%20echo%20-en%20"/t"%20%20%20%20%20%20%20%20else%20%20%20%20%20%20%20%20%20%20%20%20echo%20-n%20"%20%20%20%20"%20%20%20%20%20%20%20%20fi%20%20%20%20done%20%20%20%20for%20((j=0;j<=i;j++))%20%20%20%20do%20%20%20%20%20%20%20%20if%20[%20${MAX}%20-le%206%20];then%20%20%20%20%20%20%20%20%20%20%20%20echo%20-en%20"/t/t"${a[$j]}%20%20%20%20%20%20%20%20else%20%20%20%20%20%20%20%20%20%20%20%20echo%20-en%20${a[$j]}%20%20%20%20%20%20%20%20fi%20%20%20%20doneechodone
运行结果:
12.条件测试的多种方法 返回目录
语法格式:
格式1:test expression
格式2:[ expression ]
格式3:[[ 测试表达式 ]]
注:中括号与表达式之间前后都有空格
格式1与格式2是等价的;格式3为扩展的test命令,在 [[ ]] 中可以使用通配符进行模式匹配,如&&,||,>, <等操作符可以应用于[[ ]]中,但不能应用于[ ]中;对整数的关系运算,也可以使用Shell的算术运算符 (()).
关于各种测试操作符只需要在终端man test 即可得到详细描述:
常用的文件测试操作符号 | 说明 |
-f file | 若文件存在且为普通文件则真 |
-d file | 若文件存在且为目录则真 |
-s file | 若文件存在且不为空(文件大小非0)则真 |
-e file | 若文件存在则真,区别于-f |
-r file | 若文件存在且可读则真 |
-w file | 若文件存在且可写则真 |
-x file | 若文件存在且可执行则真 |
-L file | 若文件存在且为链接文件则真 |
f1 -nt f2 | 若文件f1 比文件 f2 新则真 |
f1 -ot f2 | 若文件f1 比文件 f2 旧则真 |
字符串测试操作符的作用:比较两个字符串是否相同、字符串长度是否为0,字符串是否为null等
“=”比较两个字符串是否相同,与 “==”等价,如 if [ "
常用字符串测试操作符 | 说明 |
-z "string" | 若string长度为0,则真 |
-n "string" | 若string长度步为0,则真 |
“string1”= ”string2“ | 若string1等于string2则真,可以使用“==”代替“=” |
“string1”!= ”string2“ | 若string1不等于string2则真 |
注意:测试符“==”,“=”,“!=”好前后均需与测试字符串之间留空格!!!
在[ ]中使用的比较符 | 在(())和[[]]中使用的比较符 | 说明 |
-eq | == | 相等 |
-ne | != | 不等 |
-gt | > | 大于 |
-ge | >= | 大于或等于 |
-lt | < | 小于 |
-le | <= | 小于或等于 |
在[]中的使用 | 在[[]]中的使用 | 说明 |
-a | && | 与,两端均为真则真 |
-o | || | 或,两端有一个为真则真 |
! | ! | 非,相反则真 |
语法:
case "字符串变量" in
值1)指令1...
;;
值2)指令2...
;;
*)指令
;;
esca
给字符串显示不同的颜色:
shell脚本中echo可以显示不同颜色的字符,格式如下:
格式如下(参考http://www.cnblogs.com/wish123/p/4131825.html): echo -e "/033[字背景颜色;文字颜色m字符串/033[0m" 例如: echo -e "/033[41;36m something here /033[0m" 其中41的位置代表底色, 36的位置是代表字的颜色 1、字背景颜色和文字颜色之间是英文的";" 2、文字颜色后面有个m 3、字符串前后可以没有空格,如果有的话,输出也是同样有空格下面利用case来该给定的字符串加上不同的颜色:
%201%20#!/bin/bash%202%20#Paint%20given%20chars%20with%20given%20color%203%20usage="Usage:chars%20{black|red|green|yellow|blue|purple|white}"%204%20%20[[%20$#%20-ne%202%20]]%20&&{%20%205%20%20%20%20%20%20echo%20"${usage}"%20%206%20%20%20%20%20%20exit%201%207%20}%208%20BLACK="/033[1;30m";%20RED="/033[1;31m"%20;GREEN="/033[1;32m";%20YELLOW="/033[1;33m"%209%20BLUE="/033[1;34m";%20PRUPLE="/033[1;35m";%20WHITE="/033[1;37m"10%20COLOR_END="/033[0m"11%2012%20chars=$113%20selected_color=$214%2015%20case%20${selected_color}%20in16%20%20%20%20%20black)%20res=${BLACK}17%20;;18%20%20%20%20%20red)%20res=${RED}19%20;;20%20%20%20%20%20green)%20res=${GREEN}21%20;;22%20%20%20%20%20yellow)%20res=${YELLOW}23%20;;24%20%20%20%20%20blue)%20res=${BLUE}25%20;;26%20%20%20%20%20purple)%20res=${PURPLE}27%20;;28%20%20%20%20%20white)%20res=${WHITE}29%20;;30%20%20%20%20%20*)%20echo%20'Input%20color%20is%20not%20supported'31%20%20%20%20%20%20%20%20echo%20${usage}32%20%20%20%20%20%20%20%20exit%20133%20;;34%20esac35%2036%20echo%20-e%20"${res}"$1"${COLOR_END}"
18. 当型循环和直到型循环 返回目录
while条件语句,条件满足一直执行command
while condition do commanddone
until语法,条件满足就退出,目前很少用,作为了解
until condition do commanddone
#!/bin/bashi=10while%20(($i>=1))do%20%20%20%20echo%20$i%20%20%20%20((i--))done
使用until实现上面同样的功能:
#!/bin/bashi=10until%20[%20$i%20-eq%200%20]%20do%20%20%20%20echo%20$i%20%20%20%20((%20i--%20))done在实践中经常需要使用while来处理日志文件,下面实际中使用while读取文本的方法:
#1exec%20<FILEwhile%20read%20linedo%20%20%20%20cmddone#2cat%20${FILE}%20|%20while%20read%20linedo%20%20%20%20cmddone#3while%20read%20linedo%20%20%20%20cmddone<FILE
19.for循环 返回目录
for循环语法结构1:
for%20var%20in%20var_listdo%20%20%20%20cmd1%20%20%20%20cmd2%20%20%20%20...done
在此结构中,%20“in%20var_list”可以省略,省略时,相当于in%20"
@",例如fori就相当于foriin" @",例如fori就相当于foriin"@".for循环语法结构2:
for%20((exp1;exp2;exp3))%20#与C语言一样do%20%20%20%20cmd1%20%20%20%20cmd2%20%20%20%20...done#!/bin/bashfor%20i%20in%2010%209%208%207%206%20do%20%20%20%20echo%20$idone
下面代码实现同样的功能:
#!/bin/bashfor i in {10..6}do echo $idone
#!/bin/bashfor i in $(seq -s " " 10 -1 6)do echo $idone
获取当前目录下的所有文件名,打印
#!/bin/bashfor i in $(ls) do echo $idone
打印9*9乘法表:
%201%20#!/bin/bash%202%20for%20a%20in%20$(%20seq%201%209%20)%203%20do%204%20%20%20%20%20for%20b%20in%20$(%20seq%201%209%20)%205%20%20%20%20%20do%20%20%206%20%20%20%20%20%20%20%20%20if%20[%20$a%20-ge%20$b%20];then%207%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20-en%20"$a%20x%20$b%20=%20$((a*b))%20%20"%208%20%20%20%20%20%20%20%20%20fi%20%20%209%20%20%20%20%20done10%20echo%20"%20"11%20done12%2013%20echo
新闻热点
疑难解答