shell脚本学习总结

shell脚本学习总结


cut命令 用法

cut命令用于从文件或者标准输入中读取内容并截取每一行的特定部分并送到标准输出截取的方式有三种:一是按照字符位置,二是按照字节位置,三是使用一个分隔符将一行分割成多个field,并提取指定的fields。

cut命令有5个参数,其中-c,-b,-f分别表示"character","byte"以及"field"截取方式。当采用field模式截取时,需要用"-d"参数指定一个分隔符,分割符只能为单个字符。另外还有一个"-s",suppress,表示如果行中没有给出的分割符则不输出该行(默认为如果没有分隔符则将该行原封不动输出)

例如:# echo Long,long ago,ddddddd,hhhhhhhhhhh | cut -f 2- -d ,

long ago,ddddddd,hhhhhhhhhhh 按照’,’把这个字符串分开

cat a.txt|cut -c 2-5输出a.txt每行的第25个字符

cat a.txt|cut -c 2,5输出每一行的第2和第5个字符

cut主要用在处理数字或文字数据信息,这是因为通常会以某些字符作为分隔符,然后加以分割,取得所需要的数据,尤其在处理log日志文件中。但是,cut在处理多空格连续的数据时,往往会比较吃力

grep 用法

      grep命令形式为:grep [-acinv] ‘搜索字符串’ filename

-a: 将二进制以文本文件的方式搜索

-c: 计算找到搜索字符串的次数

-i: 忽略大小写,大小写视为相同

-n: 顺序输出行号,如这句话是在第12行,就会输出12

-v: 打印不包含搜索字符串的所有行

 

说明:grep可以解析一行文字,取得关键字,若该行存在关键字,就把这一行都列出来

 

用例:grep -n ‘oo’ a.txt 将a.txt中所有包含oo串的行挑出来,并显示行号

grep -n ‘[^g]oo’ a.txt   将a.txt中所有包含oo串并且oo前面不是g的行挑出来,并显示行号

grep -n ‘^[^a-zA-Z]’ a.txt 找出a.txt中以非英文字母开头的行,并打印行号

grep -n ‘\.$’ a.txt 找出a.txt中所有以’.’结尾的行,并打印行号

grep -v ‘^$’ a.txt |grep -v ‘^#’ 取消显示空白行和注释行

num=”2.6.27”

grep -v $num a.txt 找出不含2.6.27的那些行

grep -v “$num” a.txt 找不出含2.6.27的那些行,这种方法也正确

grep -v ‘$num’ a.txt     错误,$num不能被解析

grep -n ‘go\{2,5\}g’ a.txt显示a.txt中以g开头,并且包含25o,最后接1g的字符串。这里,{有特殊的意义,所以要用转义字符\{

注意:[^]为集合字符的反向选择

         ^ 为代表行首的字符

         $ 为代表行尾的字符

         [] 内表示有一个字符

         ! 用在’ ’中,表示非的意思

  这里比较纠结的,就是!与^两个的不同,这次没有弄明白,期待以后吧~~

排序命令 sort wc uniq

1、 Sort

Sort可以用来排序, 而且是根据不同的数据类型来排序。

用法如下:sort [-fbMnrtuk] [fileor stdin]

参数:

-f :忽略大小写的差异

-b:忽略最前面的空格部分

-M:以月份的名字来排序

-n:使用纯数字进行排序(默认的是以文字类型来排序)

-r:反向排序

-t:分隔符,默认为tab

-u:就是uniq,相同的数据就出现一次

-k:按那个字段来排序

例如:

想对文件/etc/passwd:进行分割,拿第三段进行排序,所需要命令如下:

cat /etc/passwd |sort –t ‘:’ –k 3

这个要求也可以换种方法做:cat/etc/passwd |cut –d ‘:’ –f 3|sort

 

2、 uniq

如果排序完成,重复的数据只需要一个,就可以用uniq命令

用法:uniq [-ic]

参数:

-i :忽略大小写

-c :统计次数,对于重复出现的数据,统计出现的次数

3、 wc

Wc是用来统计行数,字数,字符数的

用法:wc [-lmw]

-l :显示多少行

-w:显示多少个字(英文单词)

-m-c:显示多少个字符

4、 tee

Tee为双向重导向命令,将上一步获得数据同时导向到另外一个输出流中。

用法:tee [-a] filename

参数:

-a:以append的方式将结果写入文件filename

5、 split

Split是将文件进行分割,可以按照行数或大小进行分割,大文件分割为小文件。

用法:split [-lb] filePREFIX

-b:后接要拆分文件的大小,可加单位,如b,k,m

-l:按行数进行拆分,后接要拆分成的行数

例:/etc/termcap700K,现在要拆分成300K大小的文件

split –b 300k /etc/termcap /tmp/termcap

这样,就会生成三个小文件,分别为/tmp/termcapaa,/tmp/termcapbb, /tmp/termcapcc。如果需要的话,可以进行设置,使其生成数字开头的文件

split –b 300k –d /etc/termcap /tmp/

 

awk用法

简介:sed比较适合用于整行数据的处理,而awk比较适合处理单行的数据,对单行中的每个字段进行处理

Awk的用法如下:

awk ‘条件类型1{动作1} 条件类型2{动作2}……’ filename

-F :指定新的分隔符

-v :对变量进行赋值操作

注:默认的字段分隔符为“空格键”或“[tab]键”

条件类型如下所示,包括逻辑运算和内置变量赋值,比较

awk的内置变量:

NF          每一行拥有的字段总数

NR         当前处理的是第几行的数据

FS          当前的分隔符,默认的是空格键,也叫出入域分隔符,可以通过-F来指定

RS          输入记录分隔符

OFS        输出域分隔符

ORS              输出记录分隔符

awk 的逻辑运算字符

>     大于

<     小于

>=   大于或等于

<=   小于或等于

==   等于

!=    不等于

用例:

last |awk ‘{print $1 ”\t” $3}’ 作用是显示last中每行的第1和第三列。

这里要注意,$0代表一整行的数据,$1代表第一列,与传统的风格略有不同。

cat /etc/passwd |awk ‘BEGIN {FS=”:”} $3< 10 {print $1”\t”$3}’

上式等价于cat/etc/passwd |awk -F”:” ‘BEGIN $3 < 10 {print$1”\t”$3}’

在/etc/passwd文件中以冒号(:) 来分隔字段,查找第三栏小于10以下的数据,并且显示出第一栏和第三栏。

这里注意BEGIN必须得加,说明是从第一条记录开始,否则,只能从第二条才开始变化。Awk相当于说明有一个预处理的块,这块中对分隔符等进行初始化。

awk还提供了另一个特殊块,叫作 END块。awk在处理了输入文件中的所有行之后执行这个块。通常,END块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

cat a.txt| awk ‘NR==1{printf “%10s %10s%10s %10s\n”,$1,$2,$3,”Total”} NR>=2{total=$2+$3 printf “%10s %10d %10d%10.2f\n”,$1,$2,$3,total}’

以上这个命令比较长,第一行与其它行的输出方式不同,并且用到了printf,而不是print,这里就不知道是为什么了。

cat a.txt|awk ‘/foo/ {print}’ 打印出包含字符串foo的那些行

cat a.txt|awk ‘/[0-9]+\.[0-9]*/ {print}’ 打印出包含浮点数的行

cat a.txt|awk ‘BEGIN{x=0} /^$/{x=x+1}END{print “the empty line number is ” x}’打印出文件a.txt中的所有空行

awk -F "|" '{print $1}'  file按照新的分隔符“|”进行操作。
awk  'BEGIN { FS="[: \t|]" } {print$1,$2,$3}'   file 通过设置输入分隔符(FS="[: \t|]")修改输入分隔符。

 Sep="|"

 awk -F $Sep '{print$1}'  file按照环境变量Sep的值做为分隔符。   

 awk -F '[ :\t|]''{print $1}' file 按照正则表达式的值做为分隔符,这里代表空格、:、TAB、|同时做为分隔符。

 awk -F '[][]'    '{print$1}' file按照正则表达式的值做为分隔符,这里代表[、]

awk 'BEGIN {"date"|getline d;print d}' 通过管道把date的执行结果送给getline,并赋给变量d,然后打印。

awk 'BEGIN{FS="[()]";num=0} $2!= "'$cmp_str'" {num=num+1} $2 == "'$cmp_str'" {print num}'这是个纠结的表达式,从中,要知道,指定FS时,必须用双引号awk中调用内部变量num时,只需要参数名num就行,不需$以及各种引号,系统变量必须用单引号,但如果是字符串,并且进行比较,则必须用”’’”,即单引号和双引号都要用

awk -v num=0 -F '[()]' '$2 !="'$cmp_str'" {num=num+1} $2 == "'$cmp_str'" {print num} '上一个表达式的作用于这个相同,通过-F指定是,可以用单引号或双引号,可以通过-v为新设置的参数赋初值。

注意:

1)      非变量的文字部分,要用双引号来定义,指定FS时,也需要用双引号

2)      {}内的操作,如果有多个命令时,可以使用分号(;)隔开,或者直接用回车键

3)      awk中,变量可以直接使用,无需加上$

4)      awk的操作内{}也支持if(条件)

5)      awk还可以用于循环计算,相当好用,以后再学习

6)      awk中调用系统变量必须为单引号,若为双引号,表示字符串

Flag=abcd

awk‘{print ‘$Flag’}’ 结果为abcd

awk‘{print “$Flag”}’ 结果为$Flag

7)      {}之前的判断语句判断符之间空格可要可不要。


sed用法

注意:sed后面跟的所有操作,都必须用(‘ ’)一对单引号包含

sed命令形式为:sed [-nefr] [动作]

参数:

-n :使用安静模式。在一般sed的用法中,所有来自stdin的数据一般都会显示在屏幕上。如果加上-n参数,只有处理过的那一行才会列出

-e:直接在命令行模式上进行sed的操作编辑

-f直接将sed的操作写在一个文件中,-f filename 则可以执行filename内的sed操作

-rsed的操作支持的是扩充正则表达式的语法

-i:表示就地修改文件,源文件也发生变化(这里不确定)

操作说明:[n1[,n2]]function

n1,n2:不一定存在,一般代表“选择进行操作的行数”

function的如下操作:

a:新增,a的后面可以接字符串,而这些字符串会在新的一行出现,即在下一行加入这个字符串

c:替换,c的后面可以接字符串,这些字符串可以替换n1,n2之间的行

d:删除,因为是删除,所以d后面往往不加任何内容

i:插入,i的后面接字符串

p:打印,即打印某个选择的数据

q:退出命令

s:搜索,不但可以搜索,还可以替换,如1,20s/abc/def/g

n:下一行,即在匹配的下一行执行某些操作

r:读,从文件中读出内容

w:写,将筛选出的内容写入一个文件

yy的作用与s类似,也是进行替换,可能是不许要g(这里不确定)

举例说明:

nl a.txt|sed ‘2,5d’ 将a.txt中2至5行外的所有数据打印,nl相当于cat+显示行号

nl a.txt|sed ‘2,5c miss the lines’ 将2-5行的数据替换为miss the lines 并打印

nl a.txt|sed ‘1,$s/abc/def/g’ 把所有的abc换为def,注意,如果没有g的话,只会在一行中第一次出现的地方替换,这一行后面的匹配项不替换

cat /etc/man.conf| sed -e ‘s/#.*$//g’ -e ‘/^$/d’ 将man.conf文件中所有空行和注释行全都删除

这里的.*用的很妙,#.*$表示从#开始,一直到这一行的结束。单独的.表示后面跟一个字符,*表示后面跟0到任意多个上一个字符

sed -f fix.sed myfile > myfile2 从文件fix.sed中读取出sed命令,处理文件myfile,将处理完后的结果保存在myfile2中

DEF=”default”

num=0

sed 's/\('$DEF'=\).*$/\1'$num'/' file将文件file中default=后面的所有字符替换为0。这里要注意的是 ,sed中引用外面定义的变量,一定要用’$num’的形式,否则会被视为字符串

删除:d命令

sed ‘2d’ example 删除example文件中的第二行

sed ’2,5d’ example 删除example文件中的第二到第五行

sed ‘$d’ example 删除example文件中的最后一行

sed ‘/test/’d example 删除example文件中所有包含test的行

替换:s命令

sed -n ‘s/^abc/def/p’ example -n和p搭配,表示只显示替换部分。将example文件中以abc开头的行替换为def,并且只打印替换的行

sed ‘s/^192.168.0.1/&localhost/’example&表示替换字符串中被找到的部分。所有以192.168.0.1开头的行都会被替换成它自己+localhost,即192.168.0.2localhost

sed -n ‘s/\(love\)able/\1rs/p’ example love被标记为1,将loveable 替换为lovers,并且只打印被替换的行。这句话等价于sed -n ‘s/loveable/lovers/p’example

sed ‘s#10#100#g’ example #被认为是新的分隔符,这句话的意思是将example中的10替换为100,把这里的#看成/即可

选定行的范围:逗号

sed -n ‘/test/,/tmp/p’ example 所有在example test和tmp所确定的范围内的行全部打印

sed -n ‘5,/^test/p’ example 打印从第5行开始,一直到以test开头的行之间的所有行

sed ‘/test/,/tmp/s/$/add end’ example 对于模板test和tmp之间的行,在每行的末尾用字符串add end替换

多点编辑:e命令

sed -e ‘1,5d’ -e ‘s/test/tmp/’ example (-e) 选项允许在同一行里执行多条命令。第一条命令是删除1到5行,第二条命令为将test替换为tmp。要说明的是,两条命令的先后顺序会影响最终的输出结果

文件操作:rw命令

sed ‘/test/r filename’ examplefilename中的内容将被取出来,放在与test匹配的行的后面,如果匹配了多行,则每一行都会有显示

sed -n ‘/test/w file’ example 匹配文件example中出现test的每一行,并将这些行写在文件file中

下一个:n命令

sed ‘/test/{n;s/aa/bb/g;}’ example 将example文件中与test匹配的下一行中的所有aa变为bb

退出:q命令

sed ‘10q’ example 显示10行文件,然后退出


shell中的通配符

*            表示前边的字符出现任意连续0次到多次

?            表示任意一个字符

[list]              匹配list中的任意单一字符

[!list]     匹配除list中的任意单一字符

[c1-c2]   匹配c1到c2中的任意单一字符,如[0-9],[a-z]

{string1,string2,….} 匹配string1,string2中的任意一个字符串

^abc      匹配以abc为开头的句子

abc$      匹配以abc为结尾的句子

/<abc      匹配以abc为开头的词

abc/>      匹配以abc为结尾的词

+:         ERE              匹配任意1个或多个前置表达式

?        ERE             匹配0个或一个前置正则表达式

.:          匹配任意单个字符

a*:              匹配字符a的任意长度,可以是0,注意,这里的a是没用的,要想表示a后面有任意多个任意字符,需要用a.*来表示

.*:        匹配任意字符的任意长度

.:          表示后面一个任意字符

\{n,m\}   BRE              区间表达式,匹配在它前面的单个字符重复出现的次数区间,\{n,m\}表示出现n至m次,n,m值介于0到255之间

\( \)                BRE              将\(与\)间的模式存储在特殊的“保留空间”。最多可以有9个独立的子模式,例如 \(ab\)\(def\).*\2\1 ,可以匹配以abdef开头,defab结尾,中间有任意多个任意字符的字符串

\n           BRE              重复在\(与\)方括号内第n个子模式至此点的模式

{n,m}     ERE              与前面提到的BRE中的\{n,m\}一样,只不过括号前没有反斜杠

[:alnum:] 字符集   用[:和:] 将关键字组合起来的POSIX字符集,alnum表示数字或字母,alpha表示数字字母,digit表示数字字符    lower表示小写字母,upper表示大写字母

[.ch.]      排序符号       指的是将多个字符序列视为一个单位,字符必须按这个序列出现。如[ab[.ch.]de]则匹配a、b、d、e或者成对的ch,而单独的c或h是不行的

[=e=]      等价字符集    列出的是与e应视为等价的一组字符。

 

注意:

1>    在BRE中,方括号表达式中,所有其他的meta都会失去其特殊含义。所以[]*\.] 分别匹配字符],*,反斜杠\,和小数点.。这里要注意的是,如果’]’要进入集合,就将其放在列表最前面,如果减号-进入集合,也将其放在最前面,如果两者同时进入集合,就将右括号]放最前面,-放最后面。

2>    在BRE中,^和$只有放在开头和结尾处才有特殊用途,否则被视为普通字符。但是在ERE中,^和$永远是meta。

扩展的正则表达式

在扩展正则表达式ERE(ExtendedRegular Expressions)中,大部分与基本正则表达式BRE(Basic RegularExpressions)中的方法是一致的,但有一些有较大的区别。

1、 匹配单个字符

匹配单个字符与BRE中基本一致,不同的一点在于awk中,如果要匹配([]-\)这四个字符时,需要用反斜杠,即\[\]\-\\

2、后引用不存在

在ERE中,\(和\)匹配的是字面上的左括号和右括号

3、匹配单个表达式和多个表达式

匹配单个表达式没有区别,在匹配多个表达式时,有较大的区别。ERE中的q{10,20}BRE中的q\{10,20\}是同样的意思。

ERE中有另外两个meta字符,可更细腻地处理匹配控制:

?        匹配0个或1个前置正则表达式,ab?c匹配abcabbc

+        匹配1个或多个前置正则表达式,ab+c匹配abcabbc,但不能匹配ac

4、交替运算符|

       方括号表达式主要用于匹配单个字符,但对于字符序列,就需要用交替运算符。如read|write就用来匹配read或write。

       这里要注意的是,交替运算符优先级是最低的。

5、分组

       圆方括号((…))可以提供分组功能。如(why)+用于匹配出现一个或联系多个why。由于交替运算符|的优先级太低,往往需要用分组来处理多字符的问题。

       例如:read|write+ 表示正好有一个read或者一个write后面接任意个数的e字符

       (read|write)+   表示有一个或重复多个read,或者有一个或重复多个write。(这里有一些疑问,需要验证一下)

       ((read|write)[[:space:]]*)+用以匹配多个连续出现的read或是write,且中间可能被空白字符隔开

6、停驻文本匹配

       在ERE中,^和$永远是meta字符。所以,像ab^cd与ab$cd这样的表达式都是有效的,只不过是匹配不到任何东西。

7、ERE中的优先级

[..] [= =] [: :]

用于字符对应的方括号符号

\metacharacter

转义的meta字符

[]

方括号表达式

()

分组

* + ? {}

重复前置的表达式

无符号 (no symbol)

连续字符

^ $

锚点

|

交替

 

test 和方括号[]

test功能很多,用于判断文件及其相关属性,比较字符串,比较数字的大小等。

用法:

test 表达式

判断文件属性:

检查文件类型test -e filename

-e

是否存在

-b

是否为块设备

-f

是否为文件

-c

是否为字符设备

-d

是否为目录

-S

是否为套接字文件

检查文件属性

-r

文件是否可读

-s

文件是否为“非空白文件”

-w

文件是否可写

 

 

-x

文件是否可执行

 

 

比较两个文件test file1 -nt file2

-ot

(older than) 判断文件file1是否比file2

-nt

(newer than)判断文件file1是否比file2

-ef

判断文件file1file2是否为同一文件,判断是否指向同一个inode

 

字符串比较:

test -z string

判断string是否为空,空则返回true

test -n string

判断是否为空,空则返回false-n可以省略

test str1 = str2

判断字符串str1 str2是否相等,相等,返回true

test str1 != str2

不相等,返回true

 

数值比较:

用法:test$num1 -eq $num2

-eq

相等

-lt

num1 小于num2

-ne

不相等

-ge

Num1 大于等于num2

-gt

num1 大于num2

-le

Num1 小于等于num2

多重条件判断:

用法:test-r filename -a -w filename

-a

(and)两个同时成立,返回true

-o

(or) 有一个成立,返回true

!

条件求反,如test ! -x filenamefilename不可执行时,返回true

举例:

[ “$yn” == “Y” –o “$yn” == “y” ]&& echo ”input y” || echo “input error” 如果输入为Y或y,则输出input y,否则,输出input error

注意:

1>    test在使用时,当比较字符串时,必须用双引号””,对应的变量必须也用双引号””。如:test “$file1”-ot “/home/test”

2>    上面说的也不完全正确,就是说比较的字符串中,有空格等,必须要用””,即中括号内的变量,常量最好都用双引号来设置

3>    在使用方括号命令时,括号内的每个组件之间必须有空格,否则就会出错

4>     使用[]时,判断字符串相等用==,而test命令中为=

5>    整数条件表达式,shell中没有>,<这些符号,必须用-ne,-ge,-lt

 

关于shell的语法

1>    If语句

if [ 条件判断表达式1] &&/|| [ 条件判断表达式2 ];then

  条件判断表达式成立是,需执行的命令

elif [        条件判断表达式3 ];then

…………..

else

……………….

fi

注意:];之间不能有空格

2>    Case…esac语句

这个语句的语法如下:

case $变量名称in

         “第一个变量内容”)

                程序段

                ;;

         “第二个变量内容”)

                程序段

                ;;

         *)

                程序段

                ;;

esac

说明:每个程序段的最后都必须用两个分号(;;)表示程序段的结束

网上看到这样一个例子:

#test.sh

INPUT_FILE=2.log

if[ -s $INPUT_FILE ] then

while read RECORD

do

case $RECORD in

^\/\**) #以/*开头的行

echo "find /*"

;;

*\*\/$) #以*/结尾的行

echo "find */"

;;

\#*)#以#号开头的行

echo "find #"

;;

*)

echo $RECORD

esac

done< $INPUT_FILE

else

echo"please select anther file to split up"
fi

3>    For语句

For语句用于循环次数确定的情况,不仅可以处理数字,还可以处理字符串。处理数字的语法如下:

for(( 初始值; 限制值;执行步长 ))

do

       程序段

done

for处理字符串,如下:

forvar in con1 con2 con3

do

       程序段

done

var变量的内容在循环工作中,每次循环分别为con1,con2,con3

4>    While语句

常见的有两种,while和until,分别如下:

while or until [ condition ]

do

       程序段落

done

while语句还可以用于文件操作,如:

whileread line

do

       程序段

done<file

表示从file中读取一行字符串,放到变量line中,在程序段中对line进行操作。

5>     使用函数功能

函数在shell中类似于自定义的执行命令,最大的功能是,可以简化程序代码。函数的语法是这样的:

functionf_name(){

       程序段

}

其中,f_name是自定义的执行命令名称,程序段是要执行的内容。函数的设置一定要写在最前面,这样才能执行时找到可用的程序段

函数在调用时,调用方法如下:

f_name参数列表

注意,这里的参数列表是传递给这个函数的参数列表,函数拥有内置变量,它的内置变量与shell脚本类似,函数名称为$0,以后的分别为$1,$2。函数内部的$0,$1shell脚本的$0,$1是不同的

 

Read用法

Read表示读入数据,可以从标准输入设备或者其它文件中,得到输入后,read将值放在一个变量中。

Read读文件时,每次读取出文件中的一行,通常与while 一起使用。

Read用法:

read [-p (提示语句)] [-n(字符个数)] [-t(等待时间)] [-s(不回显)]

参数说明:

-p:指定提示语句,注意要用“”

-n:指定要读取的字符数,当read n个字符后,自动退出,并将输入数据赋值给变量

-t:指定read命令等待输入的秒数,当计时器满时,read命令返回一个非0退出状态

-s:指定的数据不显示在显示器上,(实际上,数据是显示的,只不过与背景颜色相同)

举例如下:

read name 从键盘上读入数据放到name中

read -p “input the name” name 显示提示信息 input the name ,并读入到name中

read -t 5 name 从键盘上读入name,5秒后,如果没有输入,就自动退出

 

Echo用法

echo 输出是,默认的是换行,可以通过指定’\c’,让输出不换行,或者用-e命令

举例如下:

echo “\“this is a test\”” 输出结果为”this is a test”,其中\表示转义

echo -n “this is a test”,输出结果为 thisis a test,并且不回车

echo -e “this is a test\n”,输出结果为 this is a test ,并且回车,这里-e指的是后面的字符串中有转义字符

 

Declare 用法

declare 为声明某个变量的类型,具体如下:

-r 只读类型

declare -r var 声明变量var为只读类型,相当于c中的const,等价于readonly var

-i 整数类型

declare -i num 声明变量num为整数类型

num=3

echo “num=”$num 输出num的值,为3

num=three 用字符串给num赋值

echo “num=”$num 输出num的值为0,因为上一步对其用字符串赋值

 

declare -i num=$num+1 引用其他变量时,可以这样做,说明,+左右不能有空格,这里相当于是let运算

declare -i num=0

for(( i=0; i<=100; i++ )) do

       #num=$num+$i            正确,+号前后不能有空格

       num=”$num+ $i”  正确,如果出现空格,必须用双引号,这一点,与let相似

done

如果把变量指定为整数类型,即便没有let,expr等命令,也允许进行特定的算数运算

num=6/3

echo $num输出的结果为6/3

declare -i num

num=6/3

echo $num 输出的结果为 2

-a 数组

declare -a indices 声明indices为一个数组

indices=abc,与indices[0]=abc表达的含义相同

indicies[1]=def

echo ${indicies[0]} 输出结果为abc

echo ${indicies[*]} 输出结果为abc def

-f 函数

用法为declare -f[function_name]

不加函数名,将列出脚本之前定义的所有函数,加函数名的话,只列出这个函数的名字

 

注意:

1、 对于变量的赋值,不能加空格符

2、 If,while语句等,关键字与表达式之间必须加空格,[ ] 中也必须有空格与中括号两边区分开来

 

脚本的跟踪与调试

脚本跟踪调试命令为:sh[-nvx] scripts.sh

参数说明:

-n:不执行脚本,仅检查语法错误

-v:执行脚本前,先将脚本内容输出到屏幕上

-x:将使用的脚本内容显示在屏幕上,这是最好用的命令


判断是否全为数字

判断一个字符串是否全是英文字母的方法有以下几种:

1、在case语句中判断

case $string in

*[!a-zA-Z]*) return $failure ;;这个表达式的意思是,字符串中出现了a-zA-Z以外的字符,则返回错误

2、用一个表达式判断

expr length “$string” 求的字符串string的长度

test=`echo $string|grep‘[a-zA-Z]\{‘$length’\}’`表示有length个字符,全是大小写字母

if [ “$test” == “” ]then 如果test为空说明并非全是英文字母

return$failure 返回出错信息

fi

 

Shell中的特殊变量

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

$@:      命令行中输入的所有参数串

$*:       以一个单字符串显示所有向脚本传递的参数

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

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

$-:        显示shell使用的当前选项,与set命令功能相同

$?:              显示最后命令的退出状态 ,0表示成功,其它任何值表示错误


数值运算操作


(())运算

在$(())中,shell提供完整的算数运算能力,而且使用与c相同的运算符和优先级

语法:

((表达式1,表达式2))

特点:

1>    在双括号内,所有表达式可以跟c一样,如a++b—

2>    在双括号内,所有变量可以不加$

3>    双括号内,可以做算术运算,也可以做逻辑运算

4>    支持多个表达式,各表达式之间用’,’隔开

举例:

echo $(( (1==1) &&(1==0) )) 输出结果为0,括号内为逻辑表达式

sum =$((i+j)) sum的值为i和j的和

((sum=i+j)) sum的值为i和j的和,此方法与上式等价

注意:

(())内的表达式,在运算符左右可以有空格,写法比较自由,可以采用松散或紧凑的方式。如sum=$((1+1))sum=$(( 1 + 1 )),这两种写法都正确


Let运算

Let中,表达式的变量前不必加$,如果表达式中出现空格或其它特殊字符,则必须用双引号引起来。

Let 不支持++ -- ,操作,此外,提供了方幂运算符”**”

语法:

let 变量=表达式or  let “变量=表达式

举例:

let i=i+1 表达式中变量没有加$,没出现空格,故不需要双引号

let sum=11/5 运算结果为2,不需要双引号

sum=let 11/5 这个表达式与上一条一致

let sum=(-6-j)*5 如果j=9,则运算结果sum为-75,不需要双引号

let “sum= i  +  1” 出现空格,故需要加双引号

注意:

1>    在不用双引号时,等号右边以及运算符和括号的两边均不能有空格

2>    如果添加空格或其它特殊字符的话,必须用双引号(“”)引起来

3>    Let不支持++ --,操作

4>    let中,变量可以不加$符号


Expr运算

用法:

expr expression1操作符 expression2

操作符前必须加'\'用于转义,并且操作符和两个expression之间必须有空格

举例:

count=`expr $count+ 1` count值自增1

sum=`expr 7 /5`sum的值为1

sum=`expr 3\* 5` sum的值为15,注意,这里对乘号需要转义字符

sum=`expr \($a + $b \) \* $c` sum的值为(a+b*c,注意,这里需要较多的转义字符

sum=`expr4*5`sum的值为字符串4*5,因为没有加空格

注意:

1>    expr 右边以及运算符和括号的两边都必须有空格,如果采用紧凑方式写,则返回结果为算术表达式

2>    expr 命令使用时,乘号(*),左右括号都必须用转义字符反斜杠(\)进行转义

补充:

expr对于字串的操作(计算)也是很方便的,如:

# expr length"yangzhigang.cublog.cn" 求取字符串的长度,结果为21

# expr substr"yangzhigang.cublog.cn" 1 11从1到11位置抓取字符,结果为yangzhigang

# expr index "yangzhigang.cublog.cn"cu 找出cu在字符串中第一次出现的位置13


bc运算

bc不仅可以做数学运算,还可以提供精度,进制之间的转换

^表示次幂,如2^3表示2的三次方,值为8

用法:

“[scale=精度值;] [obase=输出进制;] [ibase=输入进制;]数学表达式”|bc

obase:即output base,输出结果的进制

ibase:即input base,输入数字的进制

scale:精度值,用于浮点数运算

举例:

sum=”scale=1;1.0+1.1”|bc 计算出sum的值为2.1

echo “ibase=16;obase=2;B5-A4”|bc 结果为10001

data=”scale=2;$a/$b”|bc 如果a=3,b=4,则运算结果为.75

echo 2+3|bc 输出结果为5

注意:

1>    bc后面可以接文件名,将文件中的所有表达式进行运算并显示

2>    如果只有一个表达式,可以不用””

3>    “”内运算符左右不能有空格(这一条不确定是否正确)

$[]运算

用$[]表示数学运算。将一个数学运算写到$[]符号的中括号中,中括号中的内容将先进行数学运算。

       $[] 的用法与$(()) 类似。

 

你可能感兴趣的:(shell脚本学习总结)