shell全面学习Word文件下载.docx
《shell全面学习Word文件下载.docx》由会员分享,可在线阅读,更多相关《shell全面学习Word文件下载.docx(20页珍藏版)》请在冰豆网上搜索。
);
3,除了在变量赋值和在FOR循环语句头中,BASH中的变量使用必须在变量前加"
$"
符号。
在比较详细的bash文档中,会规定使用变量要采用这样的形式:
${STR},如果你的脚本出了莫名其妙的错误,不妨看看是不是这个问题造成的。
Bash中的变量既然不需要定义,也就没有类型一说,那是不是一个变量既可以存放整数,也可以存放字符串呢?
对!
一个变量即可以被定义为一个字符串,也可以被再定义为整数。
如果对该变量进行整数运算,他就被解释为整数;
如果对他进行字符串操作,他就被看作为一个字符串。
请看下面的例子:
/bin/bash
x=2006
let"
x=$x+1"
echo$x
x="
astring."
执行一下看看?
又出现了新的关键字:
let。
关于整数变量计算,有如下几种:
+-*/%"
,他们的意思和字面意思相同,在*和/之前必须冠以反斜线,已防被SHELL先行解释。
整数运算一般通过let和expr这两个指令来实现,如对变量x加1可以写作:
或者x=`expr$x+1关于运行时参数,我们在执行脚本时有时很想传个参数进去,如:
#shmysh.shhdz(回车)好,很简单,在bash中,使用这样传进来的变量时也要在前面加“$”符号。
$#传入脚本的命令行参数个数;
$*所有命令行参数值,在各个参数值之间留有空格;
位置变元
$0命令本身(shell文件名)
$1第一个命令行参数;
$2第二个命令行参数;
...
好,编辑以下脚本:
/bin/sh
numberofvars:
$#
valuesofvars:
$*
valueofvar1:
$1
valueofvar2:
$2
valueofvar3:
$3
valueofvar4:
$4
保存文件名为my.sh,执行时传入参数:
#shmy.shabcde(回车),看到结果你就会更清楚各个变量的意思。
如果访问的参数在执行时没有传入,如有一条这样的代码:
$100而在执行时并没有输入100个参数,那取得的值为NULL
在BASH程序中如果一个变量被使用了,那么直到该程序的结尾,该变量都一直有效。
为了使得某个变量存在于一个局部程序块中,就引入了局部变量的概念。
BASH中,在变量首次被赋初值时加上local关键字就可以声明一个局部变量,如下面这个例子:
HELLO="
var1"
echo$HELLO
functionhello{
localHELLO="
var2"
echo$HELLO
}
该程序的执行结果是:
var1
var2
这个执行结果表明全局变量$HELLO的值在执行函数hello时并没有被改变。
也就是说局部变量$HELLO的影响只存在于函数那个程序块中。
BASH中的变量与C语言中变量的区别,这里我们为原来不熟悉BASH编程,但是非常熟悉C语言的程序员总结一下在BASH环境中使用变量需要注意的问题。
1,BASH中的变量在引用时都需要在变量前加上"
符号(第一次赋值及在For循环的头部不用加"
符号);
2,BASH中没有浮点运算,因此也就没有浮点类型的变量可用;
3,BASH中的整形变量的比较符号与C语言中完全不同,而且整形变量的算术运算也需要经过let或expr语句来处理;
1.1.4环境变量
由export关键字处理过的变量叫做环境变量。
我们不对环境变量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。
1.1.5Shell命令和流程控制
在shell脚本中可以使用三类命令:
1)Unix命令:
虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令。
这些命令通常是用来进行文件和文字操作的。
常用命令语法及功能
echo"
sometext"
:
将文字内容打印在屏幕上
ls:
文件列表
wc–lfile;
wc-wfile;
wc-cfile:
计算文件行数计算文件中的单词数计算文件中的字符数
cpsourcefiledestfile:
文件拷贝
mvoldnamenewname:
重命名文件或移动文件
rmfile:
删除文件
grep'
pattern'
file:
在文件内搜索字符串比如:
grep'
searchstring'
file.txt
cut-bcolnumfile:
指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:
输出.每行第5个到第9个字符cut-b5-9file.txt千万不要和cat命令混淆,这是两个完全不同的命令
catfile.txt:
输出文件内容到标准输出设备(屏幕)上
filesomefile:
得到文件类型
readvar:
提示用户输入,并将输入赋值给变量
sortfile.txt:
对file.txt文件中的行进行排序
uniq:
删除文本文件中出现的行列比如:
sortfile.txt|uniq
“|”为管道描述符,详见后文。
expr:
进行数学运算Example:
add2and3expr2"
+"
3
find:
搜索文件比如:
根据文件名搜索find.-namefilename-print
tee:
将数据输出到标准输出设备(屏幕)和文件比如:
somecommand|teeoutfile
basenamefile:
返回不包含路径的文件名比如:
basename/bin/tux将返回tux
dirnamefile:
返回文件所在路径比如:
dirname/bin/tux将返回/bin
headfile:
打印文本文件开头几行
tailfile:
打印文本文件末尾几行
sed:
Sed是一个基本的查找替换程序。
可以从标准输入(比如命令管道)读入文本,并将结果输出到标准输出(屏幕)。
该命令采用正则表达式(见参考)进行搜索。
不要和shell中的通配符相混淆。
比如:
将linuxfocus替换为LinuxFocus
cattext.file|sed'
s/linuxfocus/LinuxFocus/'
>
newtext.file
awk:
awk用来从文本文件中提取字段。
缺省地,字段分割符是空格,可以使用-F指定其他分割符。
catfile.txt|awk-F,'
{print$1"
"
$3}'
这里我们使用,作为字段分割符,同时打印第一个和第三个字段。
如果该文件内容如下:
AdamBor,34,IndiaKerryMiller,22,USA命令输出结果为:
AdamBor,IndiaKerryMiller,USA
2)概念:
管道,重定向和backtick
这些不是系统命令,但是他们真的很重要。
管道(|)将一个命令的输出作为另外一个命令的输入。
grep"
hello"
file.txt|wc–l
在file.txt中搜索包含有”hello”的行并计算其行数。
在这里grep命令的输出作为wc命令的输入。
当然您可以使用多个命令。
重定向:
将命令的结果输出到文件,而不是标准输出(屏幕)。
>
写入文件并覆盖旧文件
加到文件的尾部,保留旧文件内容。
``使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。
命令:
find.-mtime-1-typef-print
用来查找过去24小时(-mtime–2则表示过去48小时)内修改过的文件。
如果您想将所有查找到的文件打一个包,则可以使用以下脚本:
#Theticksarebackticks(`)notnormalquotes('
):
tar-zcvflastmod.tar.gz`find.-mtime-1-typef-print`
3)流程控制
1.if
"
if"
表达式如果条件为真则执行then后面的部分:
if....;
then
....
elif....;
else
fi
大多数情况下,可以使用测试命令来对条件进行测试。
比如可以比较字符串、判断文件
是否存在及是否可读等等…
通常用"
[]"
来表示条件测试。
注意这里的空格很重要。
要确保方括号的空格。
[-f"
somefile"
]:
判断是否是一个文件
[-x"
/bin/ls"
判断/bin/ls是否存在并有可执行权限
[-n"
$var"
判断$var变量是否有值
["
$a"
="
$b"
判断$a和$b是否相等
BASH是Linux操作系统的Shell,因此系统的文件必然是BASH需要操作的重要对象运算符,下面说说对文件的操作:
含义(满足下面要求时返回TRUE)
-e
文件已经存在
-f
文件是普通文件
-s
文件大小不为零
-d
文件是一个目录
-r
文件对当前用户可以读取
-w
文件对当前用户可以写入
-x
文件对当前用户可以执行
-g
文件的GID标志被设置
-u
文件的UID标志被设置
-O
文件是属于当前用户的
-G
文件的组ID和当前用户相同
file1-ntfile2文件file1比file2更新
file1-otfile2文件file1比file2更老
如if[-x/root]可以用于判断/root目录是否可以被当前用户进入
执行mantest可以查看所有测试表达式可以比较和判断的类型。
下面我们来看看变量之间的比较操作:
在比较操作上,整数变量和字符串变量各不相同,详见下表:
对应的操作
整数操作字符串操作
相同
-eq
=
不同
-ne
!
=
大于
-gt
小于
-lt
<
大于或等于
-ge
小于或等于
-le
为空
-z
不为空
-n
比较整数a和b是否相等就写做
if[$a=$b]
判断整数a是否大于整数b就写做
if[$a-gt$b]
比较字符串a和b是否相等就写作:
if[$a=$b]
判断字符串a是否为空就写作:
if[-z$a]
判断整数变量a是否大于b就写作:
if[$a-gt$b]
注意:
在“[”和“]”符号的左右都留有空格。
直接执行以下脚本:
If["
$SHELL"
/bin/bash"
];
echo"
yourloginshellisthebash(bourneagainshell)"
else
yourloginshellisnotbashbut$SHELL"
fi
变量$SHELL包含了登录shell的名称,我们和/bin/bash进行了比较。
快捷操作符
熟悉C语言的朋友可能会很喜欢下面的表达式:
/etc/shadow"
]&
&
echo"
Thiscomputerusesshadowpasswors"
这里&
就是一个快捷操作符,如果左边的表达式为真则执行右边的语句。
您也可以认为是逻辑运算中的与操作。
上例中表示如果/etc/shadow文件存在
则打印”Thiscomputerusesshadowpasswors”。
同样或操作(||)在shell编程中也是
可用的。
这里有个例子:
mailfolder=/var/spool/mail/james
[-r"
$mailfolder"
]||{echo"
Cannotread$mailfolder"
;
exit1;
}
$mailfolderhasmailfrom:
^From"
$mailfolder
该脚本首先判断mailfolder是否可读。
如果可读则打印该文件中的"
From"
一行。
如果不可读则或操作生效,打印错误信息后脚本退出。
这里有个问题,那就是我们必须有两个命令:
-打印错误信息
-退出程序
我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用。
一般函数将在下文提及。
不用与和或操作符,我们也可以用if表达式作任何事情,但是使用与或操作符会更便利很多。
2.case
case:
表达式可以用来匹配一个给定的字符串,而不是数字。
case"
in
condition1)
;
condition2)
*)
defaultstatments;
esac
下面这个程序是运用case结构进行分支执行的例子:
Hitakey,thenhitreturn."
readKeypress
$Keypress"
[a-z])echo"
Lowercaseletter"
[A-Z])echo"
Uppercaseletter"
[0-9])echo"
Digit"
*)echo"
Punctuation,whitespace,orother"
exit0
上面例子中的第四行"
readKeypress"
一句中的read语句表示从键盘上读取输入。
这个命令将在本讲义的BASH的其他高级问题中讲解。
break/continue
熟悉C语言编程的都很熟悉break语句和continue语句。
BASH中同样有这两条语句,而且作用和用法也和C语言中相同,break语句可以让程序流程从当前循环体中完全跳出,而continue语句可以跳过当次循环的剩余部分并直接进入下一次循环。
让我们再看一个例子。
file命令可以辨别出一个给定文件的文件类型,比如:
filelf.gz
这将返回:
lf.gz:
gzipcompresseddata,deflated,originalfilename,
lastmodified:
MonAug2723:
09:
182001,os:
Unix
我们利用这一点写了一个叫做smartzip的脚本,该脚本可以自动解压bzip2,gzip和zip类型的压缩文件:
ftype=`file"
$1"
`
$ftype"
in
$1:
Ziparchive"
*)
unzip"
gzipcompressed"
gunzip"
bzip2compressed"
bunzip2"
*)echo"
File$1cannotbeuncompressedwithsmartzip"
esac
您可能注意到我们在这里使用了一个特殊的变量$1。
该变量包含了传递给该程序的第一个参数值。
也就是说,当我们运行:
smartziparticles.zip时$1就是字符串articles.zip
3.selsect
select表达式是一种bash的扩展应用,尤其擅长于交互式使用。
用户可以从一组不同的值中进行选择。
selectvarin...;
do
break
done
....now$varcanbeused....
下面是一个例子:
WhatisyourfavouriteOS?
selectvarin"
Linux"
"
GnuHurd"
FreeBSD"
Other"
break
Youhaveselected$var"
下面是该脚本运行的结果:
1)Linux
2)GnuHurd
3)FreeBSD
4)Other
#?
1
YouhaveselectedLinux
4.loop
loop表达式:
while...;
....
while-loop将运行直到表达式测试为真。
willrunwhiletheexpressionthatwetestforistrue.关键字"
break"
用来跳出循环。
而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。
for-loop表达式查看一个字符串列表(字符串用空格分隔)然后将其赋给一个变量:
forvarin....;
在下面的例子中,将分别打印ABC到屏幕上:
forvarinABC;
echo"
varis$var"
下面是一个更为有用的脚本showrpm,其功能是打印一些RPM包的统计信息:
#listacontentsummaryofanumberofRPMpackages
#USAGE:
showrpmrpmfile1rpmfile2...
#EXAMPLE:
showrpm/cdrom/RedHat/RPMS/*.rpm
forrpmpackagein$*;
if[-r"
$rpmpackage"
then
===============$rpmpackage=============="
rpm-qi-p$rpmpackage
else
ERROR:
cannotreadfile$rpmpackage"
fi
这里出现了第二个特殊的变量$*,该变量包含了所有输入的命令行参数值。
如果您运行showrpmopenssh.rpmw3m.rpmwebgrep.rpm此时$*包含了3个字符串,即openssh.rpm,w3m.rpmandwebgrep.rpm.
for循环结构与C语言中有所不同,在BASH中for循环的基本结构是:
for$varin[list]
do
#codeblock
done
其中$var是循环控制变量,[list]是var需要遍历的一个集合,do/done对包含了循环体,相当于C语言中的一对大括号。
另外如果do和for被写在同一行,必须在do前面加上"
。
如:
for$varin[list];
do。
下面是一个运用for进行循环的例子:
fordayinSunMonTueWedThuFriSat
echo$day
#如果列表被包含在一对双引号中,则被认为是一个元素
fordayin"
SunMonTueWedThuFriSat"
注意上面的例子中,在for所在那行的变量day是没有加"
符号的,而在循环体内,echo所在行变量$day是必须加上"
符号的。
另外如果写成forday而没有后面的in[list]部分,则day将取遍命令行的所有参数。
如这个程序:
forparam
do
echo$param
上面这个程序将列出所有命令行参数。
for循环结构的循环体被包含在do/done对中