Shell脚本编程的常识.docx

上传人:b****8 文档编号:9240120 上传时间:2023-02-03 格式:DOCX 页数:61 大小:54.30KB
下载 相关 举报
Shell脚本编程的常识.docx_第1页
第1页 / 共61页
Shell脚本编程的常识.docx_第2页
第2页 / 共61页
Shell脚本编程的常识.docx_第3页
第3页 / 共61页
Shell脚本编程的常识.docx_第4页
第4页 / 共61页
Shell脚本编程的常识.docx_第5页
第5页 / 共61页
点击查看更多>>
下载资源
资源描述

Shell脚本编程的常识.docx

《Shell脚本编程的常识.docx》由会员分享,可在线阅读,更多相关《Shell脚本编程的常识.docx(61页珍藏版)》请在冰豆网上搜索。

Shell脚本编程的常识.docx

Shell脚本编程的常识

Shell脚本编程的常识

Shell脚本编程的常识

(这些往往是经常用到,但是各种网络上的材料都语焉不详的东西,个人认为比较有用)

七种文件类型

d目录l符号链接

s套接字文件b块设备文件

c字符设备文件p命名管道文件

-普通文件

正则表达式

从一个文件或命令输出中抽取或过滤文本时。

可使用正则表达式(RE),正则表达式是一些特殊或不很特殊的字符串模式的集合。

基本的元字符集:

^只匹配行首。

$只匹配行尾。

*一个单字符后紧跟*,匹配0个或多个此单字符。

[]匹配[]内字符,可以是一个单字符,也可以是字符序列。

可以使

用-来表示[]内范围,如[1-5]等价于[1,2,3,4,5]。

\屏蔽一个元字符的特殊含义,如\$表示字符$,而不表示匹配行

尾。

.匹配任意单字符。

pattern\{n\}匹配pattern出现的次数n

pattern\{n,\}m匹配pattern出现的次数,但表示次数最少为n

pattern\{n,m\}匹配pattern出现的次数在n与m之间(n,m为0-255)

几个常见的例子:

显示可执行的文件:

ls–l|grep…x...x..x

只显示文件夹:

ls–l|grep^d

匹配所有的空行:

^$

匹配所有的单词:

[A-Za-z]*

匹配任一非字母型字符:

[^A-Za-z]

包含八个字符的行:

^……..$(8个.)

字符类描述

以下是可用字符类的相当完整的列表:

[:

alnum:

]字母数字[a-zA-Z0-9]

[:

alpha:

]字母[a-zA-Z]

[:

blank:

]空格或制表键

[:

cntrl:

]任何控制字符

[:

digit:

]数字[0-9]

[:

graph:

]任何可视字符(无空格)

[:

lower:

]小写[a-z]

[:

print:

]非控制字符

[:

punct:

]标点字符

[:

space:

]空格

[:

upper:

]大写[A-Z]

[:

xdigit:

]十六进制数字[0-9a-fA-F]

尽可能使用字符类是很有利的,因为它们可以更好地适应非英语locale(包括某些必需的重音字符等等).

shell的引号类型

shell共有四种引用类型:

“”双引号

‘’单引号

``反引号

\反斜线

l“”可引用除$、`、\、外的任意字符或字符串,“”中的变量能够正常显示变量值。

l‘’与“”类似,不同在于shell会忽略任何的引用值。

例如:

GIRL=‘girl’

echo“The‘$GIRL’didwell”

则打印:

The‘girl’didwell

l``用于设置系统命令的输出到变量,shell会将``中的内容作为一个系统命令并执行质。

例如:

echo`date`则打印当前的系统时间。

l\用来屏蔽特殊含义的字符:

&*+^$`“|?

例如:

expr12\*12将输出144

变量设置时的不同模式:

valiable_name=value设置实际值到variable_name中

valiable_name+value如果设置了variable_name,则重设其值

valiable_name:

?

value如果未设置variable_name,则先显示未定义用户错误信息

valiable_name?

value如果未设置variable_name,则显示系统错误信息

valiable_name:

=value如果未设置variable_name,则设置其值

valiable_name-value同上,但取值并不设置到variable_name

条件测试

test命令用于测试字符串、文件状态和数字,expr测试和执行数值输出。

Test格式:

testcondition或[condition](需要特别注意的是condition的两边都要有一个空格,否则会报错),test命令返回0表示成功。

l下面将分别描述test的三种测试:

n文件状态测试(常用的)

-d测试是否文件夹

-f测试是否一般文件

-L测试是否链接文件

-r测试文件是否可读

-w测试文件是否可写

-x测试文件是否可执行

-s测试文件是否非空

n字符串测试

五种格式:

test“string”

teststring_operator“string”

test“string”string_operator“string”

[string_operator“string”]

[“string”string_operator“string”]

其中string_operator可以为:

=两字符串相等

!

=两字符串不等

-z空串

-n非空串

n数值测试

两种格式:

“number”number_operator“number”

[“number”number_operator“number”]

其中:

number_operator可以为:

-eq、-ne、-gt、-lt、-ge

例如:

NUMBER=130

[“990”–le“995”–a“NUMBER”-gt“133”]

(其中-a表示前后结果相“与”)

lexpr命令一般用于整数值,但也可以用于字符串。

n格式:

exprsrgumentoperatoroperatorargument

例如:

expr10+10

expr10^2(10的平方)

expr$value+10

n增量计数――expr在循环中最基本的用法

例如:

LOOP=0

LOOP=`expr$LOOP+1`

n模式匹配:

通过指定的冒号选项计算字符串中的字符数

例如:

value=account.doc

expr$value:

`\(.*\).doc`

输出account

命令执行顺序

&&成功执行一个命令后再执行下一个

||一个命令执行失败后再执行另一个命令

()在当前shell中执行一组命令(格式:

(命令1;命令2;……))

{}同()

例如:

cometmouth_end||(echo“hello”|maildave;exit)

如果没有(),则shell将直接执行最后一个命令(exit)

脚本调试

最有用的调试脚本的工具是echo命令,可以随时打印有关变量或操作的信息,以帮助定位错误。

也可使用打印最后状态($?

)命令来判断命令是否成功,这时要注意的是要在执行完要测试的命令后立即输出$?

,否则$?

将会改变。

Set命令也可以用来辅助脚本测试:

Set–n读命令但是不执行

Set–v显示读取的所有的行

Set–x显示所有的命令及其参数

(要关闭set选项,只要把-换成+就可以了,这里有点特殊,要注意一下)

一些常用的小trick

打印一些头信息

command<

……

……

dilimiter

以分界符号dilimiter中的内容作为命令的标准输入

常用在echo命令中,这样就避免了没输出一行就要使用一个echo命令,同时,输出格式的调整也相应变得简单了。

例如:

echo<

************************************************

hello,welcometousemyshellscript

************************************************

something_message

将在屏幕上输出:

************************************************

hello,welcometousemyshellscript

************************************************

一、利用<<的分解符号性质还可以自动选择菜单或实现自动的ftp传输

也就是利用分解符号的性质自动选择菜单。

例如:

./menu_choose>>output_file2>&1<

2

3

Y

Choose

则自动在执行脚本的过程中一步步作出选择:

2,3,Y

<<这种性质决定了它是理想的访问数据库的有用工具,可以用它来输入面对数据库提示时所作的各种选择。

创建一个长度为0的空文件

执行>file_name命令或touchfile_name命令。

一些常用的shell变量

$#传递到脚本的参数个数

$*以一个单字符串显示所有向脚本传递的参数(可大于9个)

$$脚本运行的当前进程的ID号

$!

后台运行的最后一个进程的ID号

$@与$#相同,但使用时加引号,并在引号中返回每个参数

$-显示shell使用的当前选项

$?

显示最后命令的退出状态,0表示无错误(这个变量也常常用来打印输出,在脚本调试时标记某个shell命令或某个函数是否正确执行,但是要注意,$?

记载的是最近的函数或命令的退出状态,因此打印时应该立即打印以获得正确的信息)

$0的使用

在变量中有一种位置变量$n,用来存放函数调用或脚本执行时传入的参数,其中$0表示函数名或脚本名,需要注意的是,这时的脚本名传递的是包含全路径的脚本名。

从$1-$9表示传入的第一到第九个参数,这样的参数表示不能多于九个,如果多于九个,可以使用下面将要提到的shift指令来读取。

因为$0存放函数名或脚本名,因此我们可以通过echo$0来输出调用信息,但是,由于存放的是全路径名,我们可以利用一个shell命令来得到脚本名,basename$0将得到$0中名字的部分,而与之相反的,dirname$0将得到$0中路径的部分。

Shift的运用

用head或tail指令指定查阅的行数

例如:

查阅文件前20行:

head–20file_name

查阅文件后10行:

tail–10file_name

awk使用规则

awk是一种很棒的语言。

awk适合于文本处理和报表生成,它还有许多精心设计的特性,允许进行需要特殊技巧程序设计。

与某些语言不同,awk的语法较为常见。

它借鉴了某些语言的一些精华部分,如C语言、python和bash(虽然在技术上,awk比python和bash早创建)。

awk是那种一旦学会了就会成为您战略编码库的主要部分的语言。

第一个awk

让我们继续,开始使用awk,以了解其工作原理。

在命令行中输入以下命令:

$awk'{print}'/etc/passwd

您将会见到/etc/passwd文件的内容出现在眼前。

现在,解释awk做了些什么。

调用awk时,我们指定/etc/passwd作为输入文件。

执行awk时,它依次对/etc/passwd中的每一行执行print命令。

所有输出都发送到stdout,所得到的结果与与执行catting/etc/passwd完全相同。

现在,解释{print}代码块。

在awk中,花括号用于将几块代码组合到一起,这一点类似于C语言。

在代码块中只有一条print命令。

在awk中,如果只出现print命令,那么将打印当前行的全部内容。

这里是另一个awk示例,它的作用与上例完全相同:

$awk'{print$0}'/etc/passwd

在awk中,$0变量表示整个当前行,所以print和print$0的作用完全一样。

如果您愿意,可以创建一个awk程序,让它输出与输入数据完全无关的数据。

以下是一个示例:

$awk'{print""}'/etc/passwd

只要将""字符串传递给print命令,它就会打印空白行。

如果测试该脚本,将会发现对于/etc/passwd文件中的每一行,awk都输出一个空白行。

再次说明,awk对输入文件中的每一行都执行这个脚本。

以下是另一个示例:

$awk'{print"hiya"}'/etc/passwd

运行这个脚本将在您的屏幕上写满hiya。

:

多个字段

awk非常善于处理分成多个逻辑字段的文本,而且让您可以毫不费力地引用awk脚本中每个独立的字段。

以下脚本将打印出您的系统上所有用户帐户的列表:

$awk-F":

"'{print$1}'/etc/passwd

上例中,在调用awk时,使用-F选项来指定":

"作为字段分隔符。

awk处理print$1命令时,它会打印出在输入文件中每一行中出现的第一个字段。

以下是另一个示例:

$awk-F":

"'{print$1$3}'/etc/passwd

以下是该脚本输出的摘录:

halt7

operator11

root0

shutdown6

sync5

bin1

....etc.

如您所见,awk打印出/etc/passwd文件的第一和第三个字段,它们正好分别是用户名和用户标识字段。

现在,当脚本运行时,它并不理想--在两个输出字段之间没有空格!

如果习惯于使用bash或python进行编程,那么您会指望print$1$3命令在两个字段之间插入空格。

然而,当两个字符串在awk程序中彼此相邻时,awk会连接它们但不在它们之间添加空格。

以下命令会在这两个字段中插入空格:

$awk-F":

"'{print$1""$3}'/etc/passwd

以这种方式调用print时,它将连接$1、""和$3,创建可读的输出。

当然,如果需要的话,我们还可以插入一些文本标签:

$awk-F":

"'{print"username:

"$1"\t\tuid:

"$3"}'/etc/passwd

这将产生以下输出:

username:

haltuid:

7

username:

operatoruid:

11

username:

rootuid:

0

username:

shutdownuid:

6

username:

syncuid:

5

username:

binuid:

1

....etc.

外部脚本

将脚本作为命令行自变量传递给awk对于小的单行程序来说是非常简单的,而对于多行程序,它就比较复杂。

您肯定想要在外部文件中撰写脚本。

然后可以向awk传递-f选项,以向它提供此脚本文件:

$awk-fmyscript.awkmyfile.in

将脚本放入文本文件还可以让您使用附加awk功能。

例如,这个多行脚本与前面的单行脚本的作用相同,它们都打印出/etc/passwd中每一行的第一个字段:

BEGIN{

FS=":

"

}

{print$1}

这两个方法的差别在于如何设置字段分隔符。

在这个脚本中,字段分隔符在代码自身中指定(通过设置FS变量),而在前一个示例中,通过在命令行上向awk传递-F":

"选项来设置FS。

通常,最好在脚本自身中设置字段分隔符,只是因为这表示您可以少输入一个命令行自变量。

我们将在本文的后面详细讨论FS变量。

BEGIN和END块

通常,对于每个输入行,awk都会执行每个脚本代码块一次。

然而,在许多编程情况中,可能需要在awk开始处理输入文件中的文本之前执行初始化代码。

对于这种情况,awk允许您定义一个BEGIN块。

我们在前一个示例中使用了BEGIN块。

因为awk在开始处理输入文件之前会执行BEGIN块,因此它是初始化FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。

awk还提供了另一个特殊块,叫作END块。

awk在处理了输入文件中的所有行之后执行这个块。

通常,END块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

规则表达式和块

awk允许使用规则表达式,根据规则表达式是否匹配当前行来选择执行独立代码块。

以下示例脚本只输出包含字符序列foo的那些行:

/foo/{print}

当然,可以使用更复杂的规则表达式。

以下脚本将只打印包含浮点数的行:

/[0-9]+\.[0-9]*/{print}

还有许多其它方法可以选择执行代码块。

我们可以将任意一种布尔表达式放在一个代码块之前,以控制何时执行某特定块。

仅当对前面的布尔表达式求值为真时,awk才执行代码块。

以下示例脚本输出将输出其第一个字段等于fred的所有行中的第三个字段。

如果当前行的第一个字段不等于fred,awk将继续处理文件而不对当前行执行print语句:

$1=="fred"{print$3}

awk提供了完整的比较运算符集合,包括"=="、"<"、">"、"<="、">="和"!

="。

另外,awk还提供了"~"和"!

~"运算符,它们分别表示“匹配”和“不匹配”。

它们的用法是在运算符左边指定变量,在右边指定规则表达式。

如果某一行的第五个字段包含字符序列root,那么以下示例将只打印这一行中的第三个字段:

$5~/root/{print$3}

条件语句

awk还提供了非常好的类似于C语言的if语句。

如果您愿意,可以使用if语句重写前一个脚本:

{

if($5~/root/){

print$3

}

}

这两个脚本的功能完全一样。

第一个示例中,布尔表达式放在代码块外面。

而在第二个示例中,将对每一个输入行执行代码块,而且我们使用if语句来选择执行print命令。

这两个方法都可以使用,可以选择最适合脚本其它部分的一种方法。

以下是更复杂的awkif语句示例。

可以看到,尽管使用了复杂、嵌套的条件语句,if语句看上去仍与相应的C语言if语句一样:

{

if($1=="foo"){

if($2=="foo"){

print"uno"

}else{

print"one"

}

}elseif($1=="bar"){

print"two"

}else{

print"three"

}

}

使用if语句还可以将代码:

!

/matchme/{print$1$3$4}

转换成:

{

if($0!

~/matchme/){

print$1$3$4

}

}

这两个脚本都只输出不包含matchme字符序列的那些行。

此外,还可以选择最适合您的代码的方法。

它们的功能完全相同。

awk还允许使用布尔运算符"||"(逻辑与)和"&&"(逻辑或),以便创建更复杂的布尔表达式:

($1=="foo")&&($2=="bar"){print}

这个示例只打印第一个字段等于foo且第二个字段等于bar的那些行。

数值变量

至今,我们不是打印字符串、整行就是特定字段。

然而,awk还允许我们执行整数和浮点运算。

通过使用数学表达式,可以很方便地编写计算文件中空白行数量的脚本。

以下就是这样一个脚本:

BEGIN{x=0}

/^$/{x=x+1}

END{print"Ifound"x"blanklines.:

}"}

在BEGIN块中,将整数变量x初始化成零。

然后,awk每次遇到空白行时,awk将执行x=x+1语句,递增x。

处理完所有行之后,执行END块,awk将打印出最终摘要,指出它找到的空白行数量。

字符串化变量

awk的优点之一就是“简单和字符串化”。

我认为awk变量“字符串化”是因为所有awk变量在内部都是按字符串形式存储的。

同时,awk变量是“简单的”,因为可以对它执行数学操作,且只要变量包含有效数字字符串,awk会自动处理字符串到数字的转换步骤。

要理解我的观点,请研究以下这个示例:

x="1.01"

#Wejustsetxtocontainthe*string*"1.01"

x=x+1

#Wejustaddedonetoa*string*

printx

#Incidentally,thesearecomments:

awk将输出:

2.01

有趣吧!

虽然将字符串值1.01赋值给变量x,我们仍然可以对它加一。

但在bash和python中却不能这样做。

首先,bash不支持浮点运算。

而且,如果bash有“字符串化”变量,它们并不“简单”;要执行任何数学操作,bash要求我们将数字放到丑陋的$())结构中。

如果使用python,则必须在对1.01字符串执行任何数学运算之前,将它转换成浮点值。

虽然这并不困难,但它仍是附加的步骤。

如果使用awk,它是全自动的,而那会使我们的代码又好又整洁。

如果想要对每个输入行的第一个字段乘方并加一,可以使用以下脚本:

{print($1^2)+1}

如果做一个小实验,就可以发现如果某个特定变量不包含有效数字,awk在对数学表达式求值时会将该变量当作数字零处理。

众多运算符

awk的另一个优点是它有完整的数学运算符集合。

除了标准的加、减、乘、除,awk还允许使用前面演示过的指数运算符"^"、模(余数)运算符"%"和其它许多从C语言中借入的易于使用的赋值操作符。

这些运算符包括前后加减(i++、--foo)、加/减/乘/除赋值运算符(a+=3、b*=2、c/=2.2、d-=6.2)。

不仅如此--我们还有易于使用的模/指数赋值运算符(a^=2、b%=4)。

字段分隔符

awk有它自己的特殊变量集合。

其中一些允许调整awk的运行方式,而其它变量可以被读取以收集关于输入的有用信息。

我们已经接触过这些特殊变量中的一个,FS。

前面已经提到过,这个变量让您可以设置awk要查找的字段之间的字符序列。

我们使用/etc/passwd作为输入时,将FS设置成":

"。

当这样做有问题时,我们还可以更灵活地使用FS。

FS值并没有被限制为单一字符;可以通过指定任意长度的字符模式,将它设置成规则表达式。

如果正在处理由一个或多个tab分隔的字段,您可能希望按以下方式设置FS:

FS="\t+"

以上示例中,我们使用特殊"+"规则表达式字符,它表示“一个或多个前一字符”。

如果字段由空格分隔(一个或多个空格或tab),您可能想要将FS设置成以下规则表达式:

FS="[[:

space:

]+]"

这个赋值表达式也有问题,它并非必要。

为什么?

因为缺省情况下,FS设置成单一空格字符,awk将这解释成表示“一个或多个空格或tab”。

在这个特殊示例中,缺省FS设置恰恰是您最想要的!

复杂的规则表达式也不成问题。

即使您的记录由单词"foo"分隔,后面跟着三个数字,以下规则表达式仍允许对数

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1