一、linux shell 脚本
1、描述shell程序的运行原理(可附带必要的图形说明);
Linux系统的shell作为操纵系统的外壳,为用户提供使用操纵系统的接口。它是命令语言、命令解释程序及程序设计语言的统称。
shell是用户和Linux内核之间的接口程序,假如把Linux内核想象成一个球体的中心,shell就是围绕内核的外层。当从shell或其他程序向Linux传递命令时,内核会做出相应的反应。
shell是一个命令语言解释器,它拥有自己内建的shell命令集,shell也能被系统中其他应用程序所调用。用户在提示符下输进的命令都由shell先解释然后传给Linux核心。
有一些命令,比如改变工作目录命令cd,是包含在shell内部的。还有一些命令,例如拷贝命令cp和移动命令rm,是存在于文件系统中某个目录下的单独的程序。对用户而言,不必关心一个命令是建立在shell内部还是一个单独的程序。
shell首先检查命令是否是内部命令,若不是再检查是否是一个应用程序(这里的应用程序可以是Linux本身的实用程序,如ls和rm,也可以是购买的贸易程序,如xv,或者是自由软件,如emacs)。然后shell在搜索路径里寻找这些应用程序(搜索路径就是一个能找到可执行程序的目录列表)。假如键进的命令不是一个内部命令并且在路径里没有找到这个可执行文件,将会显示一条错误信息。假如能够成功找到命令,该内部命令或应用程序将被分解为系统调用并传给Linux内核。
2、总结shell编程中所涉及到的所有知识点(如:变量、语法、命令状态等等等,要带图的哟
shell
定义变量
定义变量时,变量名不加美元符号($)如:
apple='app'
变量名的命名遵循的规则
#首个字符必须为字母
#中间不能有空格,可以使用下划线(_)
#不能使用标点符号
#不能使用bash里的关键字
使用变量
使用一个定义过的变量,只要在变量名前面加美元符号
例如
#myfather='xxx'
#echo $myfather
xxx
重新定义变量
已定义变量可以重新定义
删除变量
使用unset命令删除变量
[root@webTest ~]# app='apple'[root@webTest ~]# echo $appapple[root@webTest ~]# unset app[root@webTest ~]# echo $app
特殊变量列表
$0 : 当前脚本的文件名
$n :传递给脚本或函数的参数,n表示第n个参数。
$#:传递给脚本或函数的参数个数
$* :传递给脚本或函数的所有参数
$$ :当前shell进程Id,对于shel脚本,就是这些脚本所在的进程ID
命令行参数
运行脚本传递给脚本的参数称为命令行参数
$*和$@的区别
在没有“ ”的时候 $*和$@都以$1,$2,$3的形式显示
在有“ ”的时候 $*以$1,$2,$3整体显示,$@$1,$2,$3个体显示
环境变量
本地变量:当前shell的进程
环境变量:当前shel进程及其子进程
局部变量:某个函数执行过程
字符串
单引号
双引号
拼接字符串
运算符
Bash支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。
算术运算符
关系运算符
布尔运算符
字符串运算符
文件测试运算符
流程控制
1.if...else...fi语句
if
[ expression ]
then
Statement(s) to be executed
if
expression is
true
else
Statement(s) to be executed
if
expression is not
true
fi
2.for循环语句
for
变量
in
列表
do
command1
command2
...
commandN
done
3.while循环语句
while
command
do
Statement(s) to be executed
if
command
is
true
done
4.until 循环语句
until
command
do
Statement(s) to be executed
until
command
is
true
done
command
一般为条件表达式,如果返回值为
false
,则继续执行循环体内的语句,否则跳出循环。
例如,使用
until
命令输出0~9的数字:
#!/bin/bash
a=0
until
[ ! $a -lt 10 ]
do
echo
$a
a=`
expr
$a + 1`
done
5.case...esac语句
case
值
in
模式1)
command1
command2
command3
;;
模式2)
command1
command2
command3
;;
*)
command1
command2
command3
;;
esac
二、awk及sed工具使用详解
sed命令
sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
以上是个人理解图。
调用sed命令有两种形式:
sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)
a\
在当前行后面加入一行文本。
b lable
分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。
c\
用新的文本改变本行的文本。
d
从模板块(Pattern space)位置删除行。
D
删除模板块的第一行。
i\
在当前行上面插入文本。
h
拷贝模板块的内容到内存中的缓冲区。
H
追加模板块的内容到内存中的缓冲区
g
获得内存缓冲区的内容,并替代当前模板块中的文本。
G
获得内存缓冲区的内容,并追加到当前模板块文本的后面。
l
列表不能打印字符的清单。
n
读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。
N
追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。
p
打印模板块的行。
P(大写)
打印模板块的第一行。
q
退出Sed。
r file
从file中读行。
t label
if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
T label
错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
w file
写并追加模板块到file末尾。
W file
写并追加模板块的第一行到file末尾。
!
表示后面的命令对所有没有被选定的行发生作用。
s/re/string
用string替换正则表达式re。
=
打印当前行号码。
#
把注释扩展到下一个换行符以前。
以下的是替换标记
*
g表示行内全面替换。
*
p表示打印行。
*
w表示把行写入一个文件。
*
x表示互换模板块中的文本和缓冲区中的文本。
*
y表示把一个字符翻译为另外的字符(但是不用于正则表达式)
sed元字符集
^匹配行开始,如:/^xxx/匹配所有以xxx开头的行。
$ 匹配行结束,如:/xxx$/匹配所有以xxx结尾的行。
. 匹配一个非换行符的任意字符,如:/x.x/匹配x后接一个任意字符,最后是x。
* 匹配0个或多个字符,如:/*xxx/匹配所有模板是一个或多个空格后紧跟xxx的行。
[] 匹配一个指定范围内的字符,如/[xx]xx/匹配xxx和Xxx。
[^] 匹配一个不在指定范围内的字符,如:/[^A-F]xx/匹配不包含A-F字母开头,紧跟xx的行。
x\{m\} 重复字符x,m次,如:/1\{3\}/匹配包含3个1的行。
x\{m,\} 重复字符x,至少m次,如:/1\{3,\}/匹配至少有3个1的行。
x\{m,n\} 重复字符x,至少m次,不多于n次,如:/1\{3,6\}/匹配3~6个1的行。
sed实例
d命令
sed '3d ' apple ------ 删除apple文件第3行
sed '$d ' apple ------ 删除apple文件最后一行
sed '/test/d' apple ----- 删除apple文件中所有包含test的行
s命令
sed 's/app/apple/g' example-----在整行范围内把app替换为apple。如果没有g标记,则只有每行第一个匹配的app被替换成apple。
sed -n 's/^app/apple/p' example-----(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的app被替换成apple,就打印它。
sed 's/^192.168.0.1/&localhost/' example-----&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost。
sed 's#10#100#g' example-----不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。
e命令
sed -e '1,5d' -e 's/test/check/' example-----(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执 行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。
w 命令
sed -n '/test/w file' apple
a\命令
将 it is big 追加到以apple开头的行前面
sed '/^apple/a\/it is big' file
awk
AWK是一种优良的文本处理工具。它不仅是 中也是任何环境中现有的功能最强大的数据处理引擎之一。
1、OPTIONS:
-F:指定输入文本时所使用的字段分隔符
-v:自定义变量
2、pattern:
包括地址定界:
/pat1/,/pat2/
/pattern/
!/pattern
expression:表达式:>,<,=,>=,<=,=,!=,==,~
BEGIN:执行前的准备工作
END:执行后的收尾工作
流程控制
在awk 中两个特别的表达式,BEGIN和END,这两者都可用于pattern中。提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
if else语句
格式:
if()
语句
else
while语句
格式为:
while(表达式)
语句
do-while语句
格式为:
do
{
语句
}while(条件判断语句)
for语句
格式为:
for(初始表达式;终止条件;步长表达式)
{语句}
action
(1) Expressions (2) Control statements (3) Compound statements (4) input statements (5) output statements
awk使用
显示文本文件apple匹配(含有)字符串"xxx"的所有行。
awk '/xxx/' apple
它将显示所有匹配Sun或sun的行与匹配Moon或moon的行之间的行,并显示到标准输出上。
awk '/[Ss]un/,/[Mm]oon/' file
三、实战练习及解答
1、写一个脚本:如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;(不要怀疑,就是这么简单)
第一种方法:
[root@webTest home]# cat test.sh #!/bin/bash#$1 位置参数if [ -z $1 ];then echo "必须输入一个参数" exit 1fiif [ -e $1 ];then if [ -d $1 ]; then echo "输入的参数$1是个已存在的目录" fielse echo "输入的目录不存在,系统将自动为你创建该目录" mkdir -p $1 echo "你输入的目录为$1,且文件类型为:$(file $1|awk -F: '{print $2}')"fi[root@webTest home]# sh test.sh sss输入的目录不存在,系统将自动为你创建该目录你输入的目录为sss,且目录为: directory[root@webTest home]# sh test.sh ssssss输入的目录不存在,系统将自动为你创建该目录你输入的目录为ssssss,且目录为: directory[root@webTest home]# lltotal 120-rw-r--r--. 1 root root 244 Sep 17 17:58 1drwxr-xr-x. 192 root root 12288 Aug 4 14:53 htmldrwxr-xr-x. 2 root root 4096 Jan 21 2015 jar_logsdrwxr-xr-x. 31 root root 4096 Sep 24 20:36 m2-rw-r--r--. 1 root root 10578 Jun 26 15:13 messageCenter.htmldrwx------. 4 500 500 4096 Mar 27 16:46 micxpdrwxr-xr-x. 2 root root 4096 Feb 2 2015 packagedrwxr-xr-x. 2 root root 12288 Jan 20 2015 photosdrwxr-xr-x. 6 root root 4096 Jun 25 15:56 qianbinbin_softwaredrwxr-xr-x. 3 root root 4096 Sep 22 10:06 run_scriptdrwxr-xr-x. 2 root root 4096 Sep 24 21:35 ssdrwxr-xr-x. 2 root root 4096 Sep 24 21:40 sssdrwxr-xr-x. 2 root root 4096 Sep 24 21:39 ssssdrwxr-xr-x. 2 root root 4096 Sep 24 21:40 ssssss-rw-r--r--. 1 root root 148 Sep 17 17:04 test2.sh-rw-r--r--. 1 root root 263 Sep 17 17:59 test3.sh-rw-r--r--. 1 weihongjun weihongjun 17 Jun 25 16:25 test.htm-rw-r--r--. 1 root root 0 Jun 25 16:25 test.html-rw-r--r--. 1 root root 379 Sep 24 21:39 test.shdrwx------. 4 weihongjun weihongjun 4096 Mar 30 09:45 weihongjundrwxr-xr-x. 3 root root 4096 Jan 21 2015 workspace-rw-r--r--. 1 root root 22 Sep 24 21:27 x.txtdrwxr-xr-x. 2 root root 4096 Sep 24 21:31 xxxdrwxr-xr-x. 2 root root 4096 Sep 24 21:30 xxxxxxdrwxr-xr-x. 2 root root 4096 Sep 24 21:35 xxxxxxxxx
第二种方法:
#!/bin/bash:<
结果为:
2、写一个脚本,完成如下功能;判断给定的两个数值,孰大孰小;给定数值的方法:脚本参数,命令交互;(使用read,依然如此简单)
[root@web01-dev duoduo_test]# clear[root@web01-dev duoduo_test]# cat test2.sh #!/bin/bashread -p "Please input two integer:" -t 10 num1 num2if [ $num1 -gt $num2 ];then echo "$num1 大于 $num2."elif [ $num1 -eq $num2 ];then echo "$num1 等于 $num2."else echo "$num1 小于 $num2."fi[root@web01-dev duoduo_test]# sh test2.sh Please input two integer:2 3 2 小于 3.[root@web01-dev duoduo_test]# sh test2.sh Please input two integer:2 2 2 等于 2.[root@web01-dev duoduo_test]# sh test2.sh Please input two integer:3 23 大于 2.[root@web01-dev duoduo_test]#
3、求100以内所有奇数之和(至少用3种方法。是的这是我们的作业^_^)
1.[root@webTest home]# cat xie.sh #!/bin/bashdeclare -i sum=0for i in {1..100}do if [ $[$i%2] -eq 1 ] then sum=$[$sum+$i] fidoneecho "Sum is : $sum"[root@webTest home]# sh xie.sh Sum is : 25002.#!/bin/bashdeclare -i sum=0for i in $(seq 1 2 100)dosum=$(($sum+$i))doneecho "Sum is : $sum"[root@webTest home]# sh xie.sh Sum is : 25003.#!/bin/bashdeclare -i sum=0declare -i i=0while [ $i -le 100 ]do if [ $[$i%2] -eq 1 ] then let sum+=$i filet i++doneecho "sum is : $sum"[root@webTest home]# sh xie.sh sum is : 2500
4、写一个脚本实现如下功能:
(1) 传递两个文本文件路径给脚本;
(2) 显示两个文件中空白行数较多的文件及其空白行的个数;
(3) 显示两个文件中总行数较多的文件及其总行数;
5、写一个脚本
(1) 提示用户输入一个字符串;
(2) 判断:
如果输入的是quit,则退出脚本;
否则,则显示其输入的字符串内容;
#!/bin/bashread -p "please input a string:" -t 10 str1if [[ -z "$str1" ]]thenecho "please input something"elif [[ "$str1" == "quit" ]]thenexit 0elseecho "you inupt is $str1"fi[root@webTest home]# sh xie.sh please input a string:please input something[root@webTest home]# sh xie.sh please input a string:testyou inupt is test[root@webTest home]# sh xie.sh please input a string:quit
6、写一个脚本,打印2^n表;n等于一个用户输入的值;(不好意思,我调皮了)
#!/bin/bashif [ $# -lt 1 ]thenecho "usage: command number"exit 1fiif [ $1 -le 0 ]thenecho "please input a number big the 0"elif [ $1 -eq 1 ]thenecho "2x1=2" elsesum=2echo -n "2"for i in `seq 2 $1`do let sum*=2 echo -n "X2"doneecho "=$sum"fi[root@webTest home]# sh xie.sh usage: command number[root@webTest home]# sh xie.sh usage: command number[root@webTest home]# sh xie.sh 0please input a number big the 0[root@webTest home]# sh xie.sh 12x1=2[root@webTest home]# sh xie.sh 22X2=4[root@webTest home]# sh xie.sh 32X2X2=8[root@webTest home]# sh xie.sh 42X2X2X2=16[root@webTest home]# sh xie.sh 82X2X2X2X2X2X2X2=256[root@webTest home]# sh xie.sh 322X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2=4294967296
7、写一个脚本,写这么几个函数:函数1、实现给定的两个数值的之和;函数2、取给定两个数值的最大公约数;函数
#!/bin/bashwhile [ ture ]do echo "calcule usage is script operater number1 number2" echo "operater have 3 methord:" echo -e "1.summary usage example: \033[31msum number1 number2\033[0m" echo -e "2.Least Common Multiple (LCM) usage example: \033[31mlcm number1 number2\033[0m" echo -e "3.Greatest Common Divisor(GCD) usage example: \033[31mgcd number1 number2\033[0m" echo -e "inupt \033[31mquit\033[0m this script will exit" read -p "please input select: " op num1 num2 function testsum() { clear echo "=================================================" echo -e "\033[31msum is `expr $num1 \* $num2` \033[0m" echo "=================================================" } function gongyue() { a=$num1 local b=$num2 local tmp=0 if [ $a -lt $b ] then tmp=$a a=$b b=$tmp fi while [ $b -ne 0 ] do tmp=$(($a%$b)) a=$b b=$tmp done clear echo "=================================================" echo -e "\033[31mgongyue is $a\033[0m" echo "=================================================" } function gongbei() { clear echo "=================================================" echo -e "\033[31mgongbei is $(($num1*$num2/$a))\033[0m" echo "=================================================" } if [[ "$op" == "quit" ]] then break exit 0 elif [[ "$op" == "sum" ]] then testsum num1 num2 elif [[ "$op" == "lcm" ]] then gongyue num1 num2 elif [[ "$op" == "gcd" ]] then gongbei num1 num2 else echo "input error" fidonewhile [ ture ]do echo "calcule usage is script operater number1 number2" echo "operater have 3 methord:" echo -e "1.summary usage example: \033[31msum number1 number2\033[0m" echo -e "2.Least Common Multiple (LCM) usage example: \033[31mlcm number1 number2\033[0m" echo -e "3.Greatest Common Divisor(GCD) usage example: \033[31mgcd number1 number2\033[0m" echo -e "inupt \033[31mquit\033[0m this script will exit" read -p "please input select: " op num1 num2 function testsum() { clear echo "=================================================" echo -e "\033[31msum is `expr $num1 \* $num2` \033[0m" echo "=================================================" } function gongyue() { a=$num1 local b=$num2 local tmp=0 if [ $a -lt $b ] then tmp=$a a=$b b=$tmp fi while [ $b -ne 0 ] do tmp=$(($a%$b)) a=$b b=$tmp done clear echo "=================================================" echo -e "\033[31mgongyue is $a\033[0m" echo "=================================================" } function gongbei() { clear echo "=================================================" echo -e "\033[31mgongbei is $(($num1*$num2/$a))\033[0m" echo "=================================================" } if [[ "$op" == "quit" ]] then break exit 0 elif [[ "$op" == "sum" ]] then testsum num1 num2 elif [[ "$op" == "lcm" ]] then gongyue num1 num2 elif [[ "$op" == "gcd" ]] then gongbei num1 num2 else echo "input error" fidonecalcule usage is script operater number1 number2operater have 3 methord:1.summary usage example: sum number1 number22.Least Common Multiple (LCM) usage example: lcm number1 number23.Greatest Common Divisor(GCD) usage example: gcd number1 number2inupt quit this script will exitplease input select: sh xie ^H^H^H^H^H^H^H^H^H^H^H^H^H^H^Z[31]+ Stopped sh xie.sh[root@webTest home]# sh xie.sh calcule usage is script operater number1 number2operater have 3 methord:1.summary usage example: sum number1 number22.Least Common Multiple (LCM) usage example: lcm number1 number23.Greatest Common Divisor(GCD) usage example: gcd number1 number2inupt quit this script will exitplease input select: sum 1397 2413=================================================sum is 3370961 =================================================calcule usage is script operater number1 number2operater have 3 methord:1.summary usage example: sum number1 number22.Least Common Multiple (LCM) usage example: lcm number1 number23.Greatest Common Divisor(GCD) usage example: gcd number1 number2inupt quit this script will exitplease input select: lcm 1397 2413=================================================gongyue is 127=================================================calcule usage is script operater number1 number2operater have 3 methord:1.summary usage example: sum number1 number22.Least Common Multiple (LCM) usage example: lcm number1 number23.Greatest Common Divisor(GCD) usage example: gcd number1 number2inupt quit this script will exitplease input select: gcd 1397 2413=================================================gongbei is 26543=================================================calcule usage is script operater number1 number2operater have 3 methord:1.summary usage example: sum number1 number22.Least Common Multiple (LCM) usage example: lcm number1 number23.Greatest Common Divisor(GCD) usage example: gcd number1 number2inupt quit this script will exitplease input select: quit[root@webTest home]#
8、取给定两个数值的最小公倍数;关于函数的选定、两个数值的大小都将通过交互式输入来提供。
#!/bin/bash#sum(){# val=$[$num1+$num2] val=`expr $num1 + $num2` echo "Total value : $val"} gcd(){if [ $num1 -eq $num2 ]; then echo "max is:${num1},mini is:${num1}." exitfiif [ $num1 -gt $num2 ]; then GREAT=$num1 SMALL=$num2else GREAT=$num2 SMALL=$num1fideclare -i GCD_RESULT=1declare -i greattmp=1declare -i smalltmp=1declare -i i=1while [ $i -le $SMALL ]; do greattmp=`expr $GREAT % $i` smalltmp=`expr $SMALL % $i` [ ${greattmp} -eq 0 ] && [ ${smalltmp} -eq 0 ] && GCD_RESULT=${i} i=`expr ${i} + 1`done#LCM_RESULT=`expr $SMALL / $GCD_RESULT`#LCM_RESULT=`expr $LCM_RESULT \* $GREAT`echo "max is:${GCD_RESULT}"} lcm(){if [ $num1 -eq $num2 ]; then echo "max is:${num1},mini is:${num1}." exitfiif [ $num1 -gt $num2 ]; then GREAT=$num1 SMALL=$num2else GREAT=$num2 SMALL=$num1fideclare -i LCM_RESULT=1declare -i greattmp=1declare -i smalltmp=1declare -i GCD_RESULT=1declare -i i=1while [ $i -le $SMALL ]; do greattmp=`expr $GREAT % $i` smalltmp=`expr $SMALL % $i` [ ${greattmp} -eq 0 ] && [ ${smalltmp} -eq 0 ] && GCD_RESULT=${i} i=`expr ${i} + 1`doneLCM_RESULT=`expr $SMALL / $GCD_RESULT`LCM_RESULT=`expr $LCM_RESULT \* $GREAT`echo "mini is:${LCM_RESULT}."}prog=$(basename $0)read -p "Plz enter two integer: " num1 num2read -p "Plz enter sum | gcd | lcm : " numcase $num in sum) sum ;; gcd) gcd ;; lcm) lcm ;; *) echo "Usage:$prog sum|gcd|lcm" exit 1 esac [root@webTest home]# sh xie.sh Plz enter two integer: 91 49Plz enter sum | gcd | lcm : sumTotal value : 140[root@webTest home]# sh xie.sh Plz enter two integer: 91 49Plz enter sum | gcd | lcm : gcdmax is:7[root@webTest home]# sh xie.sh Plz enter two integer: 91 49Plz enter sum | gcd | lcm : lcmmini is:637.[root@webTest home]#