Shell编程基础笔记

(一)变量与字符串操作

1)变量的输出

Myname=Jack

Echo Hi,${Myname}con...

输出:Hi,Jackcon但如果后面接的不是英数单词,不是底线就不必使用{}隔开。

 

对于输出还有一种仿照C语言的printf命令。

:

HI=”Hello World”

Printf  “%s\n” “$HI”

对于%q会把变量中的特殊字符,用\字符转义,

HI=”ABC 123 xyz”

Printf  “%p” “$HI”

则会输出ABC\ 123\ xyz,即在空格符前面加上\

 

(2)取消与清空变量

取消变量:

Unset -v(变量名称) -p(函数名称) name

不同的参数代表要取消的是什么类型的变量。不加任何选项会先尝试取消变量,如果失败的话再试着取消与该变量名同名的函数。

清空变量:

例如:myname=”abc”

      Myname=

这样就等于清空了变量,但变量还存在,两种方法的差别就是变量是否还存在。

 

(3)变量和引号

Name=”jack

Echo “Hi, I am $name”  =>输出 Hi,I am jack

Echo ‘Hi,I am $name’ =>输出 Hi,I am $name

为什么仅仅是引号的区别输出是不同的呢,因为单引号的作用是形成一个所见即所得的字符串,不会进行任何变量替换的操作。在双引号中可以通过\来进行转义。

 

(4)变量的有效范围

变量一旦设定完毕后只在当前的shell中有效,无法影响其他shell环境的变量,一旦script文件执行完毕(该script执行是为目前的shell的子shell),回到该shell中变量不再有效。

例子:cd.sh

#! /bin/bash

Cd /usr/local

Pwd

 

script执行时,欲切换到目标目录,执行完毕后路径不会改变,因为这是在子shell中执行的,执行完成后,子shell也随即结束,又回到了父shell中,因此工作环境不会改变。

那么,如何才能使它在当前目录中进行跳转呢?很简单,只要执行.cd.sh或者source cd.sh

(5)环境变量

输出变量

当子shell产生后,它会继承父shell的环境变量等条件,因此,只要使变量成为环境变量就能为子shell取用,编程环境变量可用export这个命令:

Test=”Hello world”

Export Test

然后再在子shell中执行echo $Test就可以访问父shell中的这个值了。

另外,exportbash的内置命令,用途是吧一个变量输出,变成环境变量,使后续的各种操作(包括子shell)皆可以提取该变量的内容。

直接执行export能够列出目前所有的环境变量。相似的,用”declare -x”这个命令也能达到和export相同的效果。

当制定了一个环境变量后想取消的话就跟取消变量一样,使用unset就可以了。

 

(6)Bash的内置变量

CDPATH——用于缩短键入的路径

Export CDPATH=”/tmp/b/c:/var/log”:$HOME

Mkdir -p /tmp/b/c/a

Cd a

这样的话执行cd a时,默认是由工作目录找a,如果找不到的话就由$CDPATH中去找,可以直接切换到这个目录。

 

FUNCNAME——函数执行期间,此变量内容即为函数的名称

Function show_name()

{

Echo $FUNCNAME

}

就会输出show_name

 

IFS——定义字段分隔符。默认值为:空格,tab字符,换行字符。

例:

PL是密码文件/etc/passwd中的一行,现在要把该行的各个字段分析出来,如下ifs.sh

#! /bin/bash

 

PL=”root:x:0:0:root:/root:/bin/bash”

#重新定义IFS,要以”:”为分隔符

IFS=”:”

#j代表第几个栏数

j=0

#以循环分析各个字段

For i in $PL

do

j=$((j+1)) #j增加1

Echo $j个字段是$i

Done

执行结果:

1个字段是root

.....

7个字段是/bin/bash

 

RANDOM——随机函数,直接使用是伪随机的,因此使用前可以设定一个数作为随机种子,

RANDOM =$$  #使用shell的进程编号当做随机数种子

Echo $RANDOM

其实,linux核心提供了更具随机运算的机制,它通过虚拟文件/dev/urandom来运行,用法如下:

head -1 /dev/urandom |od -N 2|head -1 |awk ‘{print $2 *1}’

指令的意思:使用head读取urandom输出的一行位数据,通过管道交给od印出2bytes的内容,在通过管道由head取一行数据,最后由awk印出第二个字段(先乘以1)当做随机数。

 

SECONDS——当前BashShell的已执行时间(以秒为单位)

Echo $SECONDS

输出秒数。

 

TMOUT——如果TMOUT的值大于0,则bash会等待TMOUT秒后,自动结束目前的bash shell

TMOUT=3

 

$1~$n——位置参数,第一个参数为$1,如果n超过9的话要用{}括起来如${10}

$0代表执行程序的名称

$*——代表所有的位置参数,并且视为一个字符串。

例如:test.sh abc 123 xyz $*的内容字符串为”abc 123 xyz”

$@——代表各位置参数组成的串行。

例如:test.sh abc 123 xyz $@的内容为”abc”,”123”,”xyz”这三个字符串

$#——代表参数的个数

$?——代表上一个命令执行结束后的返回值,通常0代表成功,非0代表有误。

$$——代表目前bash shell的进程编号

$!——上一个后台程序的进程编号

 

(6)调整变量的属性

只读readonly用法

执行readonlyreadonly -p显示目前只读属性的变量列表

Readonly -f 函数名称——设定函数式不可改

Readonly -a 数组变量——设定是只读的数组

 

其实用declare可以进行大多数的属性调整。具体根据参数来定。

别名

建立别名:

Alias ll=’ls -l --color=auto’

取消别名:

Alias ll=ll

或者

Unalias 别名

 

(7)数组的用法

建立数组的几种方法:

A[0]=1

A[1]=”hello world”

Echo ${A[1]}

或者可以一次性设定每个元素的值

B=(12 13 14)

Echo ${B[2]}

更可以指定个别元素的索引,

C=([3]=77  [1]=100  [5]=66)

Echo ${C[5]}

这样的话分别指定了第4,2,6个元素,当指定一部分的索引时其余系统会自动续接。

E=(123  [8]=188 266)

Echo ${E[9]}

 

取出数组的所有的元素

Echo ${B[@]}

结果会输出12 13 14

@改成*一样可以取出所有的元素,这两者的区别是,${B[@]}得到的是4个以空白隔开的数字,但是${B[*]}得到一整个字符串“12 13 14

 

取得数组元素的个数

Echo ${#B[@]},结果是3,表示数组有三个元素。

 

取消数组或者数组元素

比如取消A数组

Unset A

如果想要取消某个元素的话就是

Unset A[3]

这样就等于取消了第四个元素

 

(8)Here Document

利用这个可以设定变量,基本语法为:

命令<<标记

.............

.............

标记

 

这样会把命令和标记之间的内容,利用转向输入的方式交给该命令去处理。

例如:

Info=’hello world’

Em=’text.txt’

Cat >$Em<<HERE

$info

HERE

结果就能存成文件,内容为hello world

 

控制Here Document的格式

1.关闭变量替换的功能:在第一个Here上加上单引号,然后再中间的文本如果有变量替换如$num就不会进行变量替换,而是输出$num。这在嵌入代码或注释之类的很有用。

 

利用Here Document做多行注释

:<<Here

注释1

注释2

Here

这样就添加了多行注释。

 

利用Here Document,打包C或其他语言的原始码

例:create_prg.sh

Cat<<’EOF’>hello.c

#include<stdio.h>

Int mian()

{

Printf(“hello world\n”);

Return 0;

}

EOF

 

#编译hello.c产生执行文件

Gcc -o hello hello.c

#如果编译成功,就执行

If[$? -eq 0];then

Echo “执行hello”...

Echo ./hello

./hello

Else

Echo ‘编译错误:hello.c

Fi

利用这个script夹带了一个hello.c程序的原始码,执行后会产生hello.c,然后会编译,如果可以编译则执行,这就是shell script携带攻击程序的原型。 

 

 

 

(二)高级变量

(1)测试存在性及空值:

测试变量存在性的基本用法

R=${myname -’bash’}//如果变量myname不存在的话符合判断条件,则吧-后面的字符串当做整个变量扩展的结果,并将它回传,给R。加入myname的值存在的话,r的值就是原来的值。

R=${myname:-’bash’}//测试变量不存在或其值为空,则传回默认值,这个与上面的差别在于还会判断存在性

R=${myname:=默认值}//测试变量不存在或者其值为空,给变量设一个默认值

R=${myname:?错误信息}//测试变量不存在或者其值为空,提示错误信息

R=${myname:+’true’}//如果存在的话返回true,检测存在且非空。

 

(2)取字符串切片,字符串长度

切片方法有两种:

Substr=${myname:4}//表示从第5个字符开始,截取子字符串,至字符串结束

Dir=${myname:1:3}//表示由第2个字符开始,截取3个字符长度的子字符串

 

(3)取部分位置参数

命令行参数第一个参数用$1来表示,第二个用$2表示,依次类推,例如test.sh x y z这个命令中$1就代表x$0代表命令本身。

${@:起点}//由起点开始,取得后面的所有参数。第0个位置参数是$0

${@:起点:个数}//由起点开始,取得指定个数的位置参数

 

(4)计算字符串的长度

Filename=”helloworld”

Echo ${#filename}

执行结果返回了字符串的长度,

这里总结一下:

${#变量名称}//计算字符串长度

${#数组[@]}//取得数组的元素个数

${#数组[*]}//同上

 

除了这个方法,还有一个计算字符创长度的方法,可以利用外部程序expr来做。

Str=’here you are’

Len=$(expr length “$str”)//lengthexpr的选项,用来指定要做计算字符串长度的操作

Len=$(expr “$str” : ‘.*’)//这里:后面的.*是一个代表任意多个字符的字符串样式,expr会根据此样式来对比“字符串”,等于是计算字符串的长度。

 

(5)变量扩展:对比样式

Filename=”/usr/sbin/ntpdate”

R=${filename#/*/}

对比的样式是/*/,它的意思是说:凡是一对斜线之间有字符串者,(空字符串也可以),对比符合。因为#表示的由前面取最短的,所以,对比到最短的字符串是/usr/,所以将它删除,然后传回剩下的字符串,并设置给r,结果为sbin/ntpdate

对比删除样式总结:

1${变量#样式} #由前面对比,删最短的

2${变量##样式} #由前面对比,删最长的

3${变量%样式} #由后面对比,删最短的

4${变量%%样式}#由后面对比,删最长的

5${变量/样式/替换字符串}#替换第一个对比符合的字符串

6${变量//样式/替换字符串}#替换全部对比符合的字符串

7${变量/#样式/替换字符串}#5,但由变量值开头对比

8${变量/%样式/替换字符串}#5,但由变量值末尾对比

9${变量/样式/} #删除第一个符合样式的字符串

10${变量//样式/} #删除所有符合样式的字符串

11${变量/#样式/} #9,但由变量值开头的对比

12${变量/%样式/} #9,但由变量值尾部的对比

 

 

取代或者删除部分字符串

只替换第一个找到的合适的字符串

语法:${变量/样式/替换的字符串}

Act=”mail:x:8:8”

R=${act/:/,}

执行结果:第一个替换成

Mail,x:8:8

替换全部对比符合的字符串

语法:${变量//样式/替换的字符串}

例子省略,和上面类似,就把所有的符合样式的替换成将要替换掉字符串。

对于要删除的要求来说,只要将后面的要提换成的字符串删掉。

 

 

 

(三)流程控制

If的完整语法

If 条件测试1:then

命令区域1

Elif 条件测试2:then

命令区域2

Else

命令区域3

Fi 

 

例子:

#! /bin/Bash

If  grep  -q “rm” fn.sh;then

Echo “fjind rm command”

Else

Echo “not found”

Fi 

在条件测试中,执行的命令是:grep -q “rm” fn.sh,它寻找fn.sh文件里是否有关键字rm,选项-q表示不显示,仅借助$?来传回执行结果。

 

使用Bash关键字[[ ]]组成的句子:[[判断式]]

比如说比较两个字符串

If[[ str>xyz  ]]...这个符号的判断是的前面和后面都要有一个或多个空格。

或者使用test,这是个Bash的内置命令。

If test “str” \> “xyz” #大于符号>对于Bash来言是特殊字符,要用\来转义。

或者使用内置命令[],这个和test对的用法是相同的,两者可互相改写。

If [“str” \>”xyz”]

 

 

使用-a -o进行逻辑组合

[-r filename1 -a -x filename]//这是判断filename1是否为可读和可执行-a

[-r filename1 -o -x filename]//这是判断filename1是否为可读或者可执行-o

 

&&||复用

这两个复用可以达到if-then-else的效果,列如:

[-n ${DEBUG:-}] && set -v || set +v

这段代码使用-n测试变量是否有设非空值,如果有,表示要进行排错,接着执行逻辑and的下一条命令,如果无措就执行or的那条。这也看做是一种隐形的if-then-else的用法。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值