这次小编在这里给大家整理了shell脚本学习笔记简介及基本格式(共含8篇),供大家阅读参考。同时,但愿您也能像本文投稿人“kskj11888”一样,积极向本站投稿分享好文章。
shell简介
shell英文原意是壳,贝壳的意思,在linux,unix系统中的shell是一个接受用户指令的的命令行界面。当shell执行程序时,它会请求内核启动新的进程,在该进程里执行当前序,具体的实现是shell调用fork函数产生新进程,在新进程里调用exec函数加载指定程序。shell可以执行二进制可执行文件(elf文件),或者是脚本文件(具备可执行权限)。 对于脚本文件的处理,shell会启动一个新的shell来处理。
shell脚本基本格式
因为shell的实现由很多种,linux常用的默认的shell是bash,但还有很多其他shell,如b shell, c shell等。所以我们在编写shell脚本的时候需要一种机制能搞告知内核,我们需要用到哪种shell来执行我们的脚本,
shell脚本使用脚本里的第一行来标识具体使用哪种shell。
[html]
#! /bin/bash
所有的shell脚本都以上面一行作为开始。脚本以#!作为开始,后面跟的是解释器的完整路径,路径后面还可以跟着参数,内核会根据相应的参数调用解释器。 我们编写一个简单地脚本程序nusers.sh,该脚本显示出当前登录系统的用户数量。
[html]
#! /bin/bash
who | wc -l
who命令会打印当前登录的用户的相关信息,通过管道 | 将结果传送给wc程序处理,wc -l 会打印出who命令输出信息的行数(who命令会将每个用户的信息用一行来显示)也就是用户的数量。
1111111111111清除/var/log下messages日志文件的简单命令脚本
/var/log/下日志文件时系统文件,必须有root权限:
$UID是系统的全局变量:
make && make install 表示前面成功了,执行后面的
make || make install 表示前面不成功,执行后面的
清空日志的三种方法:适合保留文件,清空内容的场合
①echo “ ”>test.log或echo >test.log
②>test.log
③cat /dev/null >test.log
22222222222:shell脚本的基础知识
shell是弱类型语言:(语法宽松,不严格)较为通用
通用的shell有标准的Bourne shll(sh)和c shell(csh)其中Bourne shell(sh)已经被bash shell取代
shell脚本的建立:
tac /etc/init.d/nfs 将文件倒着显示
相当于:head -1 /etc/init.d/nfs
①脚本开头
一个规范的shell脚本的第一行会指出由哪个程序(解释器)来执行脚本中的内容,在
333333333333linux bash 编程中一般为:
①解释器
#!/bin/bash
或
#!/bin/sh
②在linux下sh 相当于bash,
#!又称幻数,在执行bash脚本的时候,内核会根据它来确定用哪个程序来解释脚本中的内容
,这一行必须在脚本顶端的第一行,如果不是第一行,则为注释
Centos.和RedHat linux下默认的shell均为bash
④如果脚本的开头不指定解释器,那么,就要用对应的解释器来执行脚本
脚本注释
#号
444444444444444shell脚本的执行
shell脚本的执行
当shell脚本以非交互的方式运行时,它会先查找环境变量ENV,该变量指定了一个,环境文件(通常是.bashrc),然后从改环境变量文件开始执行,当读取了ENV文件后,SHELL才开始执行shell脚本中的内容,
shell脚本学习
,
Shell脚本的执行通常可以采用以下三种方式:
①bash script-name或 sh script-name(推荐使用)
②path/script-name或./script-name(当前路径下执行脚本)
③source script-name或. script-name# 注意点号
第一种方法是当脚本文件本身没有可执行权限(即文件X位为-号)时常使用的方法,这里推荐用bash执行,或者文件开头没有指定解释器,
第二种方法需要先将脚本文件的权限改为可执行(即文件加X位),具体方法:chmod u+x
script-name 或者chmod 755 script-name然后通过脚本路径,就可以直接执行脚本了
第三种方法通常是使用source或者“.” 号读入或加载指定的shell脚本文件语句,,然后,依次执行指定shell脚本文件san.sh中的所有。语句将作为当前父shell脚本father.sh进程的一部分运行,因此,使用source或者“.”点号等的可以将san.sh自身脚本中的变量的值,或者函数等的返回值传递到当前的父shell脚本father.sh中使用,这是第三种方法和前两种方法的最大区别
通过source 或“.” 点号加载执行过的脚本,在脚本结束后脚本中的变量(包括函数)值,在当前shell中依然存在,而sh和bash则不行,因此,在做shell脚本开发时。如果脚本中有需求引用其他脚本的内容,或者配置文件时,做好用“.” 点号或者source在脚本开头加载改脚本或配置文件,然后在下面的内容用可以调用source加载的脚本及文件中的变量及函数等内容。
笔试题:
已知如下命令及返回结果,请问echo $user的返回的结果为
[oldboy@test~]cat test.sh
[oldboy@test~]user=`whoami`
[oldboy@test~]sh test.sh
作者: 字体:[增加 减小] 类型:
今天做笔记稍微整理了下,但是避免不了出现错误,如果有错误麻烦大家给提出,本文最后将会共享今天的三个脚本文件,
变量
获取本机主机名
#hostname
获取本系统版本号
#uname -r
获取cpu类型
获取cpu的工作频率
cat /proc/cpuinfo
获取内存使用情况
#free -m
获取硬盘使用情况
#df
变量类型及变量操作
本地变量(一般所指)
本地变量只存在用户当前shell中,当用户退出当前shell或开器一个新的shell,所设置的变量将会不存在
设置变量
#变量名=变量值
显示变量
#echo ${变量名}
假设a=1 显示则 echo ${a}
环境变量(用的非常少)
环境变量用于所有用户进程(经常称为子进程)。登录进程称为父进程。Shell中执行的用户进程均称为子进程。不像本地变量,环境变量可用于所有子进程,这包括编辑器、脚本和应用
环境变量在用户注销时会消失,因此最好在$HOME/.bash_profile(/etc/profile)文件里直接定义
位置变量(跟脚本和函数有很大的关系)
位置变量表示$0,$1… …$9 (只有9个)
$0
$1
$2
$3
$4
$5
$6
$7
$8
$9
脚本名字
A
B
C
D
E
F
G
H
I
$0=当前脚本名称
向脚本中使用位置参数
向系统命令传递参数
特殊变量
$# 传递到脚本的参数列表个数
$* ($@) 以一个单字符串显示所有向脚本传递的参数
$$ 脚本运行的当前进程ID号
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
引用的必要性
变量操作中,脚本执行变量赋值时最容易犯的一个错误就是引用错误
例:echo abc *
echo abc ‘*‘
echo Hit the star button to exit *
引用的方式
双引号(“)(需要排除以下几个)
使用双引号可以引用除$、`、\、字符外的任意字符或字符串
单引号(‘)(比较霸道,任何都可以转成字符)
与双引号类似,不同的是shell会忽略任何引用值,
换句话说,如果屏蔽了其特殊含义,会将引号里的所有字符,都作为一个字符串。
反引号(`)(将括号内的当作命令来执行)
用于设置系统命令的输出到变量。
shell将反引号中的内容作为一个系统命令,并执行其内容
反斜杠(\)
如果一个字符有特殊含义,反斜线防止shell误解其含义,即屏蔽其特殊含义。
下述字符包含有特殊意义:& * + ^ $ ` ” | ?
脚本实例
Hello.sh
#!/bin/bash
#This is the first script
echo “Hello,World!”
执行:
chmod u+x Hello.sh
./Hello.sh
var.sh
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
echo $5
echo $6
echo $7
echo $8
echo $9
echo $10
#!/bin/bash
echo Ce “hostname\t `hostname`”
echo Ce “OScore\t `uname -r`”
echo Ce “CPUInfo\t `grep “model name” /proc/cpuinfo|awk CF: ‘{print $2}‘`”
ehco Ce “CPUMHz\t `grep “MHz” /proc/cpuinfo | awk CF: ‘{print $2}‘`”
echo Ce “MEMTotal\t `free | awk ‘$1=”Mem:”{print $2}‘`”
echo Ce “DiskInfo\t `df | grep dev |awk ‘{print $1 $2}‘`”
回顾:
脚本的结构与运行
变量的类型及用法
环境变量
本地变量
参数变量
特殊变量
变量赋值时的引用方法
作者: 字体:[增加 减小] 类型:转载
今天收获还是比较多的, 半个小时的教程看了将近3个小时
第三天:条件选择
大 纲
应用实例分析
条件测试
if…else…fi
case…in…esac
实现功能菜单:
执行脚本后
按1,显示当前时间
按2,显示CPU负载
按3,显示剩余内存
按0,退出脚本
按其他字符,提示超出选择范围后退出
分析步骤。
#date +%T
uptime awk截取
free Cm
条件测试格式
#test Coption obj
#[ -option obj ]
返回结果
表达式内容测试结果是真的
表达式内容测试结果是假的
测试的对象分类
执行结果(执行成功或失败)
文件(文件是否存在等)
文本(是否一致)
数字(数值比较)
条件测试的选项
选项作用-d目录-e是否存在-f是否是普通文件-s文件大小是否等于0-r是否可读-w是否可写-x是否可执行
逻辑操作符号
选项
作用-a
与操作-o
或操作!
非操作实例:
#test Ce /etc/passwd Ca Ce /etc/shadow 中间是a与操作,则都为0才得0
#test Ce /etc/passwd Co Ce /etc/groups 中间是o或操作,则有一真则真0
字符串操作符
== 两个字符串相等
!= 两个字符串不相等
-z 空字符串
-n 非空字符串
实例:
#test Cz $LOGNAME
#echo $LOGNAME
#echo $?
数值比较操作符
符号
说明-eq
等于-ne
不等于-gt
大于-lt
小于-ge
大于等于-le
小于等于if…else…fi 条件选择
if控制结构的基本格式:
if条件 #判断开始 可以是命令,也可以是test语句
then #如果条件为真 反值真0则执行
命令1 #执行命令1
else #如果条件为假 反值假1则执行
命令2 #执行命令2
fi #判断结束
实例(if…else…fi)1
inputtest.sh
#!/bin/bash
#input test
echo Cn “Enter your name:”
read name
#did the user just hit return
if [ “${name}” == “” ]
then
echo “You did not enter any information”
else
echo “Your name: ${name}”
fi
实例(if…else…fi)2
filecopy.sh
#!/bin/bash
#file copy
if cp /etc/passwd passwd.bak 2>/dev/null 2>/dev/null 丢掉错误提示
then
echo “Good Copy!”
else
echo “`basename $0`: error,could not copy”
fi
if…else…fi的嵌套 (两层的嵌套)
if 条件1;then
if 条件2;then
命令1
else
命令2
else
if条件3;then
命令3
else
命令4
fi
case…in…esac条件选择 (比较灵活的方式)
case语句多用于较多分支判断
case格式: (多种模式,只匹配和variable相等的模式)
case variable in
模式1)命令1…;;
模式2)命令2…;;
esac
匹配模式
* 匹配任意字符
? 匹配任意单字符
[] 匹配字符范围
case…in.esac实例1
#!/bin/bash
#case select
echo Cn “enter a number from 1 to 5:”
read NUM
case $NUM in
1) echo “you select 1″ ;;
2) echo “you select 2″ ;;
3) echo “you select 3″ ;;
4) echo “you select 4″ ;;
5) echo “you select 5″ ;;
*) echo “basename $This is not between 1 and 5″
esac
case…in.esac实例2
题目是:学生的考试成绩是0-100分,在85以上的要提示you are the best!,在70-84显示you get a good mark! ,在60-74的显示come on!,60分以下显示You must study hard!
#!/bin/bash
echo Cn “please input your mark:”
read mark
case $mark in
100|9[0-9]|8[5-9]) echo “you are the best!”;; 100、90-99、85-89
8[0-4]|7[0-9]) echo “you get a good mark!”;; 80-84、70-79
7[0-4]|6[0-9]) echo “come on!”;; 70-74、60-69
[0-5][0-9]) echo “You must study hard!”;; 00-59
esac
解决今天的问题
使用if…else…fi的方式对输入的变量进行判断,
在每个判断的分支上执行相应的语句。
menu.sh
#!/bin/bash
clear
echo “――――――Cmenu―――――C”
echo “1) Show Time”
echo “2) CPU load”
echo “3) Memory free”
echo “0) Exit”
echo “――――――――――――――C”
echo -n “Enter you chose [0-3]:”
read NUM
if [ ${NUM} -lt 0 -o ${NUM} -gt 3 ]
then
echo “This is not between 0-3.”
else
if [ “${NUM}” == “1” ]
then
echo “`date +%T`”
else
if [ “${NUM}” == “2” ]
then
echo “`uptime | awk -F ‘[,:]‘ ‘{print $7}‘`”
else
if [ “${NUM}” == “3” ]
then
echo “`free -m | awk ‘$1==”Mem:”{print $4}‘`”
else
exit
fi
fi
fi
fi
本节课回顾:
条件测试的类型
文件测试
文本测试
数值测试
逻辑测试
if…else…fi条件选择结构
case…in…esac
课后测试
1、修改menu.sh 采用非菜单式,参数传递方式来进行选择。 例如 #./menu.sh 1 输出时间
2、使用case方式来实现该菜单选择方式
Sudu答案:(难免会有错误,但是可以实现成功)
1、修改menu.sh后得出
#!/bin/bash
if [ $1 -lt 0 -o $1 -gt 3 ]
then
echo “This is not between 0-3.”
else
if [ “$1” == “1” ]
then
echo “`date +%T`”
else
if [ “$1” == “2” ]
then
echo “`uptime | awk -F ‘[,:]‘ ‘{print $7}‘`”
else
if [ “$1” == “3” ]
then
echo “`free -m | awk ‘$1==”Mem:”{print $4}‘`”
else
exit
fi
fi
fi
fi
2、 #!/bin/bash
clear
echo “――――――Cmenu―――――C”
echo “1) Show Time”
echo “2) CPU load”
echo “3) Memory free”
echo “0) Exit”
echo “――――――――――――――C”
echo -n “Enter you chose [0-3]:”
read NUM
case $NUM in
1) date +%T;;
2) uptime | awk -F ‘[,:]‘ ‘{print $7}‘;;
3) free -m | awk ‘$1==”Mem:”{print $4}‘;;
0) exit ;;
*) echo “This is not between 0-3.” ;;
esac
今天收获还是比较多的。 半个小时的教程看了将近3个小时。
虽然说if…else…fi比较容易理解,但是用case感觉简单很多,呵呵,看个人喜好吧。
每天看来看一节教程就足够了。 看多了头也会晕的。 呵呵。 继续学习吧~
作者: 字体:[增加 减小] 类型:
从昨天开始看Shell的教程到现在已经两天了,现在把记录的笔记发出来,目前是很乱,主要是留给自己看看,后续等差不多了会整理统一发布出来。
以下是Shell学习1-2天学习笔记
――――――――-我是分隔符―――――――――
硬件去执行, 内核与硬件之间进行操作。
命令解析器。
shell脚本的组成元素
系统命令
文本处理工具(sort、grep、sed、awk…)
变量
条件判断
环循结构
函数
Shell Scripts Center(SSC)
―――――――――――――――――――――――――――-
非负Grep / awk
几天。 统计Wc
Sort 排序 sort|head / sed
字段处理 awk
数据区域判断 awk |wc
显示文本: echo [选项] 文本
-n 不要自动换行
-e 解析转义符
a 发出警告音
c 最后不加上换行符号
f 换行
r 回车
彩色文本
Echo Ce “33[40;35m….]”
echo “Hello,world”
echo Ce “33[40;35mHell,world33[0m“
sort [选项]输入文件
-o 输出文件
-d 按字典顺序排序 a-z
-n 按数字大小输出 0-9
-r 逆序输出 z-a 9-0
-k 指定分类是域上的数字分类
-t 域分割符;用非空格或tab键分割域
more /etc/passwd 分页显示
sort Cd /etc/passwd|more 中间的|是反倒符号。 将前面处理的交给后面处理 先排序。后分页显示
sort Ck3 Cn Cr Ct: /etc/passwd|more
从大到小
wc [参数] [文件名]
-c 统计字符数量
-l统计行数
-w 统计单词数量 空格区分
diff [选项] 文件/目录 文件/目录
diff /etc/passwd /etc/passwd.bak
-q 仅显示有无差异,不显示详细的信息
-c 显示全部内文,并标出不同之处。
-b 不检查空格字符的不同
-B 不检查空白行
-r 比较子目录中的文件。
grep 搜索匹配 支持正则表达式
grep
-c 只打印匹配模式的行编号记数
-I 在匹配文本时忽略大小写
-n 在每行前显示其行编号
-v 逆向输出,打印不匹配的行
-f file 要匹配的字符串列表在filezhong
grep ‘[Tt]his‘ file1.txt 设置大小写
grep ‘^[^#]‘ file2.txt 不匹配行首
grep “s…n” file3.txt 匹配任意字符
sed 行编辑命令
s 替代
i 插入
a 附加
d 删除全部匹配的行
D 删除首次匹配的行
sed可以做什么(”行”为基础)
删除
改变
添加
插入
替换
示例
sed Cn ‘1,4p‘ /etc/passwd p是打印 -n 不显示原文件 打印1-4行
sed ‘/80/D‘ file.txt 首次出现80的行进行删除
sed ‘s/var/usr/g‘ file.txt 将所有的var替换成usr g代表所有
sed ‘50,$s/help/man/g‘ file.txt 替换从50行到最后一行的help替换为man 前49不管
awk 可以处理列,也可以处理行,可以定位到第几行,第几列
awk [选项] ‘awk脚本‘ 输入文件
-F fs 使用fs作为输入记录的字段分隔符 = sort Ct
-f filename 从文件filename读取awk_script(awk脚本)
-v var=value 为awk_script. 设置变量
awk的内置变量
变量功能默认FS =大写F输入字段分隔符空格或tabRS输入记录分隔符换行OFS =out FS输出字段分隔符空格或tabORS输出记录分隔符换行NF 常用当前记录非空字段的编号NR 常用从所有文件读入的记录号
示例
awk CF : ‘{print NR,$1,$2}‘ /etc/passwd
awk CF : ‘{print NR,$1,$NF}‘ /etc/passwd $NF 提取最后一行
awk CF : ‘NR%10==5{PRINT nr,$0}‘ /etc/passwd NR= 当前处理的行数 除10求余=5打印当前的行数,进行输出 $0 整行输出,比如5、15、25 打印出来
awk CF : ‘NR==8,NR==13 {print NR,$0}‘ /etc/passwd 指定8行和13行,
awk工作原理(工具)
$NF $NR $1 第一列 $2 第二列 $0 一整行
实际测试
awk CF: ‘{print $1,$3}‘/etc/passwd
awk CF: ‘{print $1,$NF}‘/etc/passwd
awk CF: ‘{print NR,$1,$NF}‘/etc/passwd NR行号
awk CF: ‘NR==5,NR==8{print NR,$1,$NF}‘/etc/passwd 指定5-8行
awk CF: ‘NR%10==5{print NR,$1,$NF}‘/etc/passwd 除10求余
课程示例测试
1、grep Cv “-” file.txt 去除所有带负号的数据 -v显示没有的 没有的话则显示只有-的
2、wc -l file.txt显示所有行数 grep Cv “-” file.txt |wc Cl 统计所有没有负数的
3、sort Cn Cr Ck4 file.txt |sed Cn ‘1p‘ 排序第四列 没有分隔符(即空格),-n数字 Cr 从大到小 sed管道 显示第一行 sed Cn不显示原文件
sort Cn Cr Ck4 file.txt |head -1 读取第一个数据 head 第一行
4、awk ‘{if($NF>3){print $0}}‘ file.txt NF 最后一列大于3 则打印一整行
5、awk ‘{if($4>0,&&$4<15){print $0}}‘ file.txt 列出第四列 大于0小于15 输出整行
awk ‘{if($4>0,&&$4<15){print $0}}‘ file.txt |wc Cl 显示行数
练习:
grep和awk
awk ‘{if($1>01011){[print $0}}‘file.txt
2、
处理命令回顾:
统计文本 wc
文本排序 sort
文本/目录对比 diff
在文件中查找关键行 grep / sed
在行文本中添、删、改 sed
在列文本中显示指定列 awk
在列文本中进行计算 awk
在列文本进行条件选择 awk
bbs.chinaunix.net/forum/viewtopic.php?t=218853show_type=new(+三问) 假如我需要在 command line 中⑦@些保留字元的功能P]的,就需要 quoting 理了, 在 bash 中,常用的 quoting 有如下三N方法: * hard quote:' ' (我),凡在 har
bbs.chinaunix.net/forum/viewtopic.php?t=218853&show_type=new(+三问)假如我需要在 command line 中⑦@些保留字元的功能P]的,就需要 quoting 理了,
在 bash 中,常用的 quoting 有如下三N方法:
* hard quote:' ' (我),凡在 hard quote 中的所有 meta. 均被P]。
* soft quote: ” “ (p引),在 soft quoe 中大部份 meta. 都被P],但某些t保留(如 $ )。(]二)
* escape : \ (反斜),只有o接在 escape (跳字符)之後的我 meta. 才被P]。
( ]二:在 soft quote 中被豁免的具w meta. 清危我不完全知道,
有待大家a充,或透^作戆lF及理解。 )
原文转自:www.ltesting.net
本文章来给大家介绍一下我自己学习linux的笔记,希望本方法对各位同学会有所帮助哦,
获取服务器IP的Shell 脚本:
代码如下复制代码#!/bin/bash
ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' |cut -d: -f2 | awk '{ print $1}'
下载整站
wget -mk www.111cn.net
判断文件的存在与否
代码如下复制代码#!/bin/bashif [ ! -f /root/log.l ]
then echo ”log.l note exist“
fi
常用语法
while 语句
代码如下复制代码#!/bin/bashecho ”enter passwd“
read passwd
while [ $passwd != ”iterse“ ];do
echo ”sorry try again“
read passwd
done
for 语句
代码如下复制代码#! /bin/bashfor i in a b c; do
echo ”$in“
done
case 语句
代码如下复制代码#! /bin/sh
echo ”Enter a number“
read number
case $number in
1)
echo ”you number is 1“
;;
2)
echo ”yo number is 2“
;;
*)
exit 1
;;
esac
if else elif fi
代码如下复制代码#! /bin/sh
echo ”Is it morning? Please answer yes or no.“
read YES_OR_NO
if [ ”$YES_OR_NO“ = ”yes“ ]; then
echo ”Good morning!“
elif [ ”$YES_OR_NO“ = ”no“ ]; then
echo ”Good afternoon!“
else
echo ”Sorry, $YES_OR_NO not recognized. Enter yes or no.“
exit 1
fi
exit 0
Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口,它接收用户输入的命令并把它送入内核去执行。实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。
Shell脚本编程学习入门是本文要介绍的内容,我们可以使用任意一种文字编辑器,比如gedit、kedit、emacs、vi等来编写shell脚本,它必须以如下行开始(必须放在文件的第一行):
代码如下复制代码#!/bin/sh
...注意:最好使用“!/bin/bash”而不是“!/bin/sh”,如果使用tc shell改为tcsh,其他类似。
符号#!用来告诉系统执行该sell脚本的程序,本例使用/bin/sh。编辑结束并保存后,如果要执行该shell脚本,必须先使其可执行:
chmod +x filename此后在该shell脚本所在目录下,输入 ./filename 即可执行该shell脚本。
Shell里的一些特殊符号
a []
shell离得函数
如果你写过比较复杂的shell脚本,就会发现可能在几个地方使用了相同的代码,这时如果用上函数,会方便很多。函数的大致样子如下:
代码如下复制代码functionname(){
# inside the body $1 is the first argument given to the function
# $2 the second ...
body
}
你需要在每个脚本的开始对函数进行声明。
下面是一个名为xtitlebar的shell脚本,它可以改变终端窗口的名称。这里使用了一个名为help的函数,该函数在shell脚本中使用了两次:
代码如下复制代码#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
cat << HELP
xtitlebar -- change the name of an xterm, gnome-terminal or kde konsole
USAGE: xtitlebar [-h] ”string_for_titelbar“
OPTIONS: -h help text
EXAMPLE: xtitlebar ”cvs“
HELP
exit 0
}
# in case of error or if -h is given we call the function help:
[ -z ”$1“ ] && help
[ ”$1“ = ”-h“ ] && help
# send the escape sequence to change the xterm titelbar:
echo -e ”33]0;$107“
#在shell脚本中提供帮助是一种很好的编程习惯,可以方便其他用户(和自己)使用和理解脚本。
命令行参数
我们已经见过$* 和 $1, $2 … $9 等特殊变量,这些特殊变量包含了用户从命令行输入的参数。迄今为止,我们仅仅了解了一些简单的命令行语法(比如一些强制性的参数和查看帮助的-h选项)。 但是在编写更复杂的程序时,您可能会发现您需要更多的自定义的选项。通常的惯例是在所有可选的参数之前加一个减号,后面再加上参数值 (比如文件名)。
有好多方法可以实现对输入参数的分析,但是下面的使用case表达式的例子无疑是一个不错的方法。
代码如下复制代码#!/bin/sh
help()
{
cat << HELP
This is a generic command line parser demo.
USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2
HELP
exit 0
}
while [ -n ”$1“ ]; do
case $1 in
-h) help;shift 1;; # function help is called
-f) opt_f=1;shift 1;; # variable opt_f is set
-l) opt_l=$2;shift 2;; # -l takes an argument ->shift by 2
--) shift;break;; # end of options
-*) echo ”error: no such option $1. -h for help“;exit 1;;
*) break;;
esac
done
echo ”opt_f is $opt_f“
echo ”opt_l is $opt_l“
echo ”first arg is $1“
echo ”2nd arg is $2“
你可以这样运行该脚本:
代码如下复制代码cmdparser -l hello -f -- -somefile1 somefile2
返回结果如下:
opt_f is 1
opt_l is hello
first arg is -somefile1
2nd arg is somefile2
这个shell脚本是如何工作的呢?脚本首先在所有输入命令行参数中进行循环,将输入参数与case表达式进行比较,如果匹配则设置一个变量并且移除该参数。根据unix系统的惯例,首先输入的应该是包含减号的参数。
shell脚本示例
一般编程步骤
现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参数。写一个框架脚本(framework.sh),该shell脚本包含了大多数脚本需要的框架结构,是一个非常不错的主意。这样一来,当我们开始编写新脚本时,可以先执行如下命令:
代码如下复制代码cp framework.sh myscript
然后再插入自己的函数。
让我们来看看如下两个示例。
二进制到十进制的转换
脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是一个用expr命令进行数学运算的例子:
代码如下复制代码#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
cat << HELP
b2d -- convert binary to decimal
USAGE: b2d [-h] binarynum
OPTIONS: -h help text
EXAMPLE: b2d 111010
will return 58
HELP
exit 0
}
error()
{
# print an error and exit
echo ”$1“
exit 1
}
lastchar()
{
# return the last character of a string in $rval
if [ -z ”$1“ ]; then
# empty string
rval=”“
return
fi
# wc puts some space behind the output this is why we need sed:
numofchar=`echo -n ”$1“ | sed 's/ //g' | wc -c `
# now cut out the last char
rval=`echo -n ”$1“ | cut -b $numofchar`
}
chop()
{
# remove the last character in string and return it in $rval
if [ -z ”$1“ ]; then
# empty string
rval=”“
return
fi
# wc puts some space behind the output this is why we need sed:
numofchar=`echo -n ”$1“ | wc -c | sed 's/ //g' `
if [ ”$numofchar“ = ”1“ ]; then
# only one char in string
rval=”“
return
fi
numofcharminus1=`expr $numofchar ”-“ 1`
# now cut all but the last char:
rval=`echo -n ”$1“ | cut -b -$numofcharminus1`
#原来的 rval=`echo -n ”$1“ | cut -b 0-${numofcharminus1}`运行时出错.
#原因是cut从1开始计数,应该是cut -b 1-${numofcharminus1}
}
while [ -n ”$1“ ]; do
case $1 in
-h) help;shift 1;; # function help is called
--) shift;break;; # end of options
-*) error ”error: no such option $1. -h for help“;;
*) break;;
esac
done
# The main program
sum=0
weight=1
# one arg must be given:
[ -z ”$1“ ] && help
binnum=”$1“
binnumorig=”$1“
while [ -n ”$binnum“ ]; do
lastchar ”$binnum“
if [ ”$rval“ = ”1“ ]; then
sum=`expr ”$weight“ ”+“ ”$sum“`
fi
# remove the last position in $binnum
chop ”$binnum“
binnum=”$rval“
weight=`expr ”$weight“ ”*“ 2`
done
echo ”binary $binnumorig is decimal $sum“
#该shell脚本使用的算法是利用十进制和二进制数权值 (1,2,4,8,16,..),比如二进制”10″可以这样转换成十进制:
代码如下复制代码0 * 1 + 1 * 2 = 2
为了得到单个的二进制数我们是用了lastchar 函数,
该函数使用wc –c计算字符个数,然后使用cut命令取出末尾一个字符。Chop函数的功能则是移除最后一个字符。
文件循环转载
你可能有这样的需求并一直都这么做:将所有发出邮件保存到一个文件中。但是过了几个月之后,这个文件可能会变得很大以至于该文件的访问速度变慢;下 面的shell脚本 rotatefile 可以解决这个问题。这个脚本可以重命名邮件保存文件(假设为outmail)为outmail.1,而原来的outmail.1就变成了 outmail.2 等等…
代码如下复制代码#!/bin/sh
# vim: set sw=4 ts=4 et:
ver=”0.1“
help()
{
cat << HELP
rotatefile -- rotate the file name
USAGE: rotatefile [-h] filename
OPTIONS: -h help text
EXAMPLE: rotatefile out
This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1[BR]
and create an empty out-file
The max number is 10
version $ver
HELP
exit 0
}
error()
{
echo ”$1“
exit 1
}
while [ -n ”$1“ ]; do
case $1 in
-h) help;shift 1;;
--) break;;
-*) echo ”error: no such option $1. -h for help“;exit 1;;
*) break;;
esac
done
# input check:
if [ -z ”$1“ ] ; then
error ”ERROR: you must specify a file, use -h for help“
fi
filen=”$1“
# rename any .1 , .2 etc file:
for n in 9 8 7 6 5 4 3 2 1; do
if [ -f ”$filen.$n“ ]; then
p=`expr $n + 1`
echo ”mv $filen.$n $filen.$p“
mv $filen.$n $filen.$p
fi
done
# rename the original file:
if [ -f ”$filen“ ]; then
echo ”mv $filen $filen.1"
mv $filen $filen.1
fi
echo touch $filen
touch $filen
这个shell脚本是如何工作的呢?在检测到用户提供了一个文件名之后,首先进行一个9到1的循环;文件名.9重命名为文件名.10,文件名.8重 命名为文件名. 9……等等。循环结束之后,把原始文件命名为文件名.1,同时创建一个和原始文件同名的空文件(touch $filen)
脚本调试
最简单的调试方法当然是使用echo命令。你可以在任何怀疑出错的地方用echo打印变量值,这也是大部分shell程序员花费80%的时间用于调试的原因。Shell脚本的好处在于无需重新编译,而插入一个echo命令也不需要多少时间。
shell也有一个真正的调试模式,如果脚本”strangescript”出错,可以使用如下命令进行调试:
代码如下复制代码sh -x strangescript7
上述命令会执行该脚本,同时显示所有变量的值。
shell脚本中还有一个不执行脚本只检查语法的模式,命令如下:
代码如下复制代码sh -n your_script
这个命令会返回所有语法错误。
我们希望你现在已经可以开始编写自己的shell脚本了,尽情享受这份乐趣吧!
★ ubuntu11.10 server i386学习笔记网络基本配置
★ 党员学习笔记
★ 学习笔记范文
★ 党员党课学习笔记
★ 数学教学学习笔记