shell编程入门.docx
《shell编程入门.docx》由会员分享,可在线阅读,更多相关《shell编程入门.docx(21页珍藏版)》请在冰豆网上搜索。
shell编程入门
Shell程序设计
学习内容:
1.什么是shell
2.语法:
变量、条件判断、程序控制
3.函数
4.命令和命令的执行
5.Here文档
6.调试
7.Grep命令和正则表达式
8.Find命令
一、什么是shell?
Shell是一个作为用户与Linux系统间接口的程序,它允许用户向操作系统输入需要执行的命令。
在一个linux系统中可以安装多个shell,这些shell和其他程序一起环绕在linux内核四周。
默认安装的标准是/bin/sh,它是GNU工具集中的bash。
使用/bin/bash–version可以查看版本。
Shell历史版本:
shcsh,、tcsh、zshksh、pdkshbash
二、shell脚本编写、运行、调试
1.脚本均以#!
/bin/bash开头。
2.脚本中的‘#’为注释符。
3.使用exit为脚本设置返回一个退出码,注意0表示的是执行成功。
示例:
#!
/bin/bash
#thisismyfirstshell!
echo“helloword!
”
exit0
4.设置脚本为可执行:
chmodu+xfilename.sh
5.执行:
./filename.sh
6.sh–x./filename.sh
三、shell语法
1、变量:
无需事先声明,直接使用,在访问时要加$在变量前。
例如:
Str=hello
echo$Str
a.这两行语句将在屏幕输出一个“hello”,shell区别大小写,定义变量时应该注意。
b.如果为变量所赋的字符串中含有空格,table或换行符应使用“”标示,例如“helloword!
”
c.变量在引号中依然有效如echo“thisis$Str!
”依然会输出:
thisishello!
练习示例:
(注:
后续的示例中只有关键部分,练习时补全)
echo“inputpassword:
”
readpasd
echo“thepasswordis$pasd”
d.如果需要输出字符$Str可以用单引号和\来处理:
‘$Str’和\$Str输出的都是$Str不是变量表示的值,shell中的变量一般都是字符串形式。
e:
环境变量,介绍几种:
$HOME当前用户的家目录
$PATH搜索命令的目录列表
$0shell脚本的名字
$#传递给脚本的参数个数
$$脚本的进程号
f:
参数变量:
$1,$2脚本的程序参数
$*列出所有参数
$@S*的一种变体,它参数不会挤在一块。
g:
变量做整形数字使用:
a=123
let“a+=1”
echo“a=$a”
2、条件
1)使用test或[]
如iftest–ffile.c
then
…..
fi
以上代码也可写成如下形式(尽量使用这种形式)
if[-ffile.c](注意:
if语句和[之间有个空格]
then
….
fi
完整示例:
#!
/bin/bash
echo“isitmorning?
Pleaseansweryesorno”
readtimeofday
if[$timeofday=“yes”];then
echo“goodmorning”
else
echo“goodafternoon”
fi
exit0
2)elif语句,在if,else语句中增加分支判断。
如下示例:
#!
/bin/bash
echo“isitmorning?
Pleaseansweryesorno”
readtimeofday
if[$timeofday=“yes”];then
echo“goodmorning”
elif[$timeofday=“no”]
then
echo“Goodafternoon”
else
echo“sorry,$timeofdaynotrecognized.Enteryesorno”
exit1
fi
exit0
3、一个与变量有关的问题。
如上程序,如果没有输入Yes和no直接按回车键,会出现什么结果呢?
程序会有出错信息。
原因是。
。
。
避免该问题产生的方法对变量使用双引号“$Str”
4、for语句
使用for语句可以循环处理一组值,这组值可以是任意字符串的集合。
它的语法形式如下:
forvariableinvalues
do
something
done
示例:
#!
/bin/bash
Forfooinhellomyname129
do
echo$foo
done
exit0
使用通配符扩展for循环
#!
/bin/sh
forfilein$(ls*.sh);do
echo$file
done
exit0
5、while语句
语法结构:
whileconditiondo
Dosometing
done
示例:
一个简陋的密码检查程序
#!
/bin/bash
echo“Enterpassword”
readpaword
while[“$paword”!
=“secret”]
do
echo“sorry,tryagain”
readpaword
done
exit0
字符串比较:
string=string
string!
=string
-nstring
-zstring
算数比较
num1–eqnum2
num1–nenum2
6、until语句,与while循环类似,只是把测试条件反过来了。
语法形式如下:
untilcondition
do
Dosomething
done
7、case语句
语法结构:
casevariablein
pattern1[|pattern]…)dosomething;;
pattern2[|pattern]…)dosomething;;
esac
该语句执行vairable与第一个pattern匹配上的语句。
例如:
#!
/bin/bash
echo“isitmorning?
Pleaseansweryesorno”
readtimeofday
case“$timeofday”in
yes)echo“goodmoring”;;
no)echo“goodafternoon”;;
y)echo“goodmorning”;;
n)echo“goodafternoon”;;
*)echo“sorry,answernotrecognized”;;
esac
exit0
匹配部分语句也可改写为:
case“$timeofday”in
yes|y|Yes|YES)echo“goodmorning”;;
n*|N*)echo“goodafternoon”;;
*)echo“sorry,answernotrecognized”;;
esac
也可以将匹配行改为;[yY]|[Yy][Ee][Ss]
8、命令列表
有时需要将好几条命令连接成一个序列。
如下
if[-fthis_file];then
if[-fthat_file];then
if[-fthe_other_file];then
echo“allfilespresent,andcorrect”
fi
fi
fi
9、AND列表
只有在前一条命令执行成功返回true才执行下一条。
语法结构:
Statement1&&Statement1&&Statement1&&…
示例:
#!
/bin/bash
touchfile_one
rm–ffile_two
if[-ffile_one]&&echo“hello”&&[-ffile_two]&&echo“there”
then
echo“inif”
else
echo“inelse”
fi
exit0
10、OR列表,直到有一条命令执行成功为止。
语法结构:
Statement1||Statement2||Statement3||…
示例:
if[-ffile_one]||echo“hello”||echo“there”
then
echo“inif”
else
echo“inelse”
fi
11、语句块
如果想在只允许使用单个语句的地方(如AND,OR)使用多条语句,可以是花括号{}来构造一个块。
如下:
Get_confirm&&{
echo“hello”
cat$tmp_file>$tracks_file
add_record_tracks
}
12、函数
要定义一个shell函数,只需写出它的名字,加上括弧,再把函数要实现的语句放在一对花括号中,如下所示:
function_name(){
Statements
}
示例:
#!
/bin/bash
foo(){
echo“functionfooisexecuting”
}
echo“thisisfoo…”
foo
echo“fooend!
”
exit0
如果在函数中没有return命令指定一个返回值,则函数返回的就是执行的最后一条命令的退出码。
示例
#!
/bin/bash
#函数部分
Yes_or_no(){
Echo“isyourname$*?
”
whiletrue
do
echo–n“Enteryesorno:
”
readx
case“$x”in
y|yes)return0;;
n|no)return1;;
*)echo“pleaseinputyesorno”
esac
done
#主程序部分
echo“originalparametersare$*”
ifyes_or_no“$1”
then
echo“HI$1,nicename”
else
echo“nevermind”
fi
exit0
在函数内部定义的变量,在函数运行后,变量依然有效,如果只想在本函数内使用临时变量,可在变量前加上local
#!
/bin/bash
foo()
{
localstr=aaaa#如果此处无local则最后的语句是可以输出aaaa的
echo"infoo$str"
}
foo
echo"over$str"
$#表示参数个数,$1为第一个参数依次类推。
($*,$@)
脚本中无函数的声明,调用某个函数前,该函数需要先被定义,所以函数的定义可以写在脚本的开始。
13、一些命令
1)break命令
在控制条件为满足之前,可以跳出for,while,until循环,后面可带参数值,来表明要跳出的循环层数,但我们不建议这么做。
2):
命令
冒号(:
)命令是一个空命令。
偶尔被运用简化逻辑,相当于true。
3)continue命令
类似C语言中的同名语句。
可使for,while,until循环跳到下一次循环继续执行,循环变量取循环列表中的下一个。
如forxin123
do
echobefore$x
continue1
echoafter$x
done
4).命令
默认情况下,shell脚本程序会在一个新创建的环境中执行,所以当脚本对环境变量所做的任何修改都会丢失,而点(.)命令允许执行的脚本程序改变当前的环境。
5)echo命令
输出一行字符内容并换行,若要使其不换行linux有两种解决方法:
echo–n“stringtooutput”
echo–e“stringtooutput\c”
(注:
-e是确保启用了反斜杠转义字符,\c代表去掉换行符,\t代表制表符,\n代表回车)
6)eval命令
eval允许对参数进行求值,如下:
foo=10
x=foo
y=’$’$x
echo$y#输出为foo
当使用eval命令时,如下
foo=10
x=foo
evaly=’$’$x
echo$y#输出为10
7)exec命令
将当前shell替换为一个不同的程序
如:
execwall“Thanksforthefish”
脚本中的这个命令会用wall命令替换当前的shell。
第二种用法是修改当前文件描述符:
exec3修改文件描述符。
8)exitn命令
一般使脚本程序以退出码n结束运行。
0表示成功,1~125是脚本可以使用的错误代码。
126表示文件不可执行,127表示命令未找到
128及以上出现一个信号
9)export命令
export命令可以将变量参数导出到子shell中,子shell中即可访问该变量。
如TESTA=testa;exportTESTA
10)expr命令
expr命令将它的参数当做一个表达式来求值。
11)printf命令
printf“formatstring”parameter1parameter2
12)return命令
return命令作用是使函数返回,后面可带返回值,如果没有返回值则默认返回最后一条命令的退出码。
13)set命令
示例:
从系统提供的参数date中提取出月份。
#!
/bin/bash
echothedateis$(date)
set$(date)
echoThemonthis$2
exit0
14)shift命令
shift命令把所有参数变量左移一个位置,使$2变成$1,$3变成$2,$1被丢弃,$0保持不变。
while[“$1”!
=“”];do
echo“$1”
shift
done
exit0
15)trap命令
Trap命令用于指定在接收信号后将要采取的行动。
语法结构:
trapcommandsignal
第一个参数是收到指定信号要采取的行动。
第二个参数是要处理的信号名称。
如果要忽略一个信号,则将第一个参数设为空字符串。
#!
/bin/bash
trap'rm-f/home/sufeng/my_shell/my_tmp_file_$$'INT
echocreatingfile/home/sufeng/my_shell/my_tmp_file_$$
date>/home/sufeng/my_shell/my_tmp_file_$$
echo"pressinterrupt(ctrl-c)tointerrupt...."
while[-f/home/sufeng/my_shell/my_tmp_file_$$];do
echoFileexists
sleep1
done
echothefilenolongerexists
trapINT
echocreatingfile/home/sufeng/my_shell/my_tmp_file_$$
date>/home/sufeng/my_shell/my_tmp_file_$$
echo"pressinterrupt(control-c)tointerrupt...."
while[-f/home/sufeng/my_shell/my_tmp_file_$$];do
echoFileexists
sleep1
done
echowenevergethere
16)unset命令
unset命令的作用是从环境中删除变量或函数。
但不能删除shell本身定义的只读变量。
#!
/bin/bash
foo="helloworld"
echo$foo
unsetfoo
echo$foo
17)find命令
find语法结构:
find[path][options][tests][actions]
path是要搜索的路径。
Options选项:
-depth在查看目录本身之前先搜素目录的内容
-follow跟随符号链接
-maxdepthsN最多搜索N层目录
-mount(或-xdev)不搜索其他文件系统中的目录
Tests选项:
-atimeN文件在N天之前被访问过
-mtimeN文件在N天之前被修改过
-name“pattern”按文件名称匹配
-newerotherfile文件比otherfile要新
-typec文件类型为c
-userusername文件的拥有者是指定用户。
对tests部分的组合:
!
(-not)测试取反
-a(-and)两个测试都必须为真
-o(-or)两个测试必须有一个为真
动作:
-execcommand执行一条命令
-okcommand同上,只是处理时回头提示
-print打印文件名
-ls对当前文件使用命令ls-dils
一个find的示例:
sufeng@linux-ecmc:
~/my_shell>find\(-name"*1.sh"-o-atime2\)-typef-execls-l{}\;
结果如下:
-rwxrwxrwx1sufengusers91Sep518:
54./bb1.sh
-rwxr--r--1sufengusers258Sep420:
41./t_fun1.sh
-rwxr--r--1sufengusers174Sep418:
11./tm_case1.sh
-rwxrwxrwx1sufengusers39Sep518:
35./cc1.sh
-rwxrwxrwx1sufengusers167Sep111:
43./tm1.sh
18)grep命令
grep语法如下:
grep[options]PATTERN[FILES]
选项含义
-c输出匹配行的数目,而不是输出匹配行
-i忽略大小写
-v对匹配模式取反
-l只列出匹配行的文件名
-E启用扩展表达式
-h取消输出行普通前缀。
示例:
grep-c-vinbb.shcc.sh
grep-cinbb.shcc.sh
19)正则表达式
字符含义
^指向一行的开头
$指向一行的结尾
.任意单个字符
[]方括号包含一个字符范围,其中任何一个字符都可以匹配,如a~e,在字符范围前面加^,即不在指定范围内。
匹配模式含义
[:
alnum:
]字母与数字字符
[:
alpha:
]字母
[:
ascii:
]ASCII字符
[:
blank:
]空格或制表符
[:
cntrl:
]ASCII控制字符
[:
digit:
]数字
[:
graph:
]非控制、非空格字符
[:
lower:
]小写字母
[:
print:
]可打印字符
[:
punct:
]标点符号字符
[:
space:
]空白字符,包括垂直制表符
[:
upper:
]大写字母
[:
xdigit:
]十六进制数字
选项含义
?
匹配是可选的,但最多匹配一次
*必须匹配0次或多次
+必须匹配1次或多次
{n}必须匹配n次
{n,}必须匹配n次或n次以上
{n,m}必须匹配n到m之间,包括n和m
以上使用的时候需要加’\’.
示例:
grepe$bb.sh以e结尾
grepa[[:
blank:
]]bb.sh以a结尾
grepTh.[[:
blank:
]]bb.sh匹配以Th开头的3个字符组成的单词
grep-E[a-z]\{10\}bb.sh匹配只有10个字符常的全由小写字母组成的单词。
20)命令的执行
$(command)
#!
/bin/bash
whoisthere=$(who)将who显示的内容给变量
echo$whoisthere
exit0
算数扩展
#!
/bin/bash
X=0
while[“$X”–ne10];do
echo$X
x=$(($x+1))
done
exit0
注意使用$时,后面有两个括弧和一个括弧是有区别的,一个是赋只给变量,两个是进行算数运算。
参数扩展
示例:
如果有两个文件1_tmp和2_tmp
#!
/bin/bash
foriin12
do
my_secret_process$i_tmp
done
此时,又有错误信息,应该为my_secret_process${i}_tmp
参数扩展说明
${param:
-default}若param为空,则值为default
${#param}给出param的长度
${param%word}从尾部开始删除与word匹配的最小部分
${param%%word}从尾部开始删除与word匹配的最长部分
${param#word}从param的头部开始删除匹配的最小部分
${param##word}从param的头部开始删除匹配的最小部分
21)here文档
可以将部分字符内容存储在脚本中,以特定的字符标示起始和结尾。
示例;
#!
/bin/bash
cat<
FUNKY!
hello
thisisahere
document
!
FUNKY!
示例2:
使用ed编辑器
#!
/bin/bash
eda_text_file<
FunkyStuff!
3
d
.,\$s/is/was/
w
q
!
FunkyStuff!
exit0
其中a_text_file文件中内容如下
Thatisline1
Thatisline2
Thatisline3
Thatisline4