认识shell

一、认识shell

什么是shell?shell为单词外壳的意思。那么这是谁的外壳?我们知道一个系统中实际工作的是那些硬件,cpu、内存、磁盘等。我们如何调用这些硬件为我们工作?实际上,硬件是由内核kernel控制的。我们可以通过kernel控制硬件,但我们不能直接和内核kernel交流。我们需要一个外壳,这个外壳就是shell来沟通kernel。何为shell脚本,其实不过是一堆命令写在一个文件中,这个文件具有执行权限。

二、变量

什么是变量?变量是脚本编程中数据表现的一中方法,变量是系统为了保留数据项在内存空间中分配一个位置或者一组位置的标识或名字。bash变量是不区分类型的,本质上都是字符串。

2.1 特殊的变量类型

本地变量:只对当前的shell进程有效,对其它shell进程无效,包含当前shell进程的子进程

[leon@localhost ~]$ test=string                                    #定义一个本地变量
[leon@localhost ~]$ echo $test
string
[leon@localhost ~]$ bash                                            #打开一个子shell
[leon@localhost ~]$ echo $test
[leon@localhost ~]$                                                  #为null值

环境变量:对当前shell进程和子进程有效,对其它shell无效

[leon@localhost ~]$ export test=string                            #定义一个环境变量
[leon@localhost ~]$ echo $test
string
[leon@localhost ~]$ bash
[leon@localhost ~]$ echo $test
string

局部变量:对shell脚本中某段代码片段有效,通常用于函数本地,通常用local来定义

[leon@localhost tmp]$ cat test.sh                                 
#!/bin/bash                                                           #定义使用哪种shell解析脚本
#    
function test {                                                     #定义一个函数
local a=local                                                        #定义一个局部变量
echo $a
}
test && echo $a
[leon@localhost tmp]$ ./test.sh 
local

位置变量:$0  $1  $2…$n

[leon@localhost tmp]$ sh test1.sh 1
[leon@localhost tmp]$ cat test1.sh 
#!/bin/bash
#
echo $0
echo $1
echo $2
[leon@localhost tmp]$ sh test1.sh string1 string2 string3        #传递位置参数
test1.sh
string1
string2

常用的特殊变量:$? $@ $* $# $$

[leon@localhost tmp]$ cat test2.sh 
#!/bin/bash
#
echo $*
echo $@
echo $#
echo $?
echo $$
[leon@localhost tmp]$ sh test2.sh string1 string2 string3 string4
string1 string2 string3 string4
string1 string2 string3 string4
4
0
1650

数组  :是特殊的变量,bash支持一维数组。数组由数组名+索引 组成。

如:a[1] a[2] a[3] … a[N]  a[hello]  a[Number]  a[string] …

2.2 变量的声明及赋值

1.不能使用系统内置变量

2.以字母,数字,下划线组成,不能以数字开头

3.见名知义

[leon@localhost tmp]$ PATH=/tmp
[leon@localhost tmp]$ ls
bash: ls: command not found
[leon@localhost ~]$ 
[leon@localhost ~]$ 1test=test
-bash: 1test=test: command not found

定义整型的变量

[leon@localhost ~]$ declare -i number=23                #使用declare -i定义一个整型变量

定义数组

可以使用declare 定义

[leon@localhost ~]$ declare -a a=(1 2 3 4)            #定义一个数组
[leon@localhost ~]$ echo ${a[@]}
1 2 3 4
[leon@localhost ~]$ b=(1 2 3 4)
[leon@localhost ~]$ echo ${b[@]}
1 2 3 4
[leon@localhost ~]$ declare -A string=([hello]='hello' [day]='sunday')    #定义一个关联型数组
[leon@localhost ~]$ echo ${string[@]}
sunday hello
[leon@localhost ~]$ logs=(/home/*)            #给变量赋值
[leon@localhost ~]$ echo ${logs[@]}
/home/leon /home/openstack /home/test

三、数组及字符串操作

3.1 数组操作

3.1.1 数组长度

${#ARRAY[*]}

${#ARRAY[@]}

[leon@localhost ~]$ declare -A string=([hello]='hello' [day]='sunday')
[leon@localhost ~]$ echo ${#string[@]} && echo ${#string[*]}
2 2

3.1.2 数组中挑选某些元素

${ARRAY[@]:offset:number}

[leon@localhost ~]$ echo ${string[@]}
sunday hello
[leon@localhost ~]$ echo ${string[@]:1:1}
sunday
[leon@localhost ~]$ echo ${string[@]:1:2}
sunday hello
[leon@localhost ~]$ echo ${string[@]:1}
sunday hello

3.1.3 数组的删除

unset ARRAY

[leon@localhost ~]$ echo ${logs[@]}
/home/leon /home/openstack /home/test
[leon@localhost ~]$ unset logs[1]        #删除索引为1的数组
[leon@localhost ~]$ echo ${logs[@]}
/home/leon /home/test
[leon@localhost ~]$ unset logs
[leon@localhost ~]$ echo ${logs[@]}

[leon@localhost ~]$

3.2 字符串操作

3.2.1 字符串取子串

${string:offset:length}  :从第offset个向右取length个字符串

[leon@localhost ~]$ string=a1b2c3d4e5f6
[leon@localhost ~]$ echo ${string}
a1b2c3d4e5f6
[leon@localhost ~]$ echo ${string:1:4}
1b2c

${string: -length}    :从右向左取length个字符串

[leon@localhost ~]$ echo ${string}
a1b2c3d4e5f6
[leon@localhost ~]$ echo ${string: -2}
f6

${string#*word} :在string中存储字符串上,自左而右,查找第一次出现word,删除字符开始到此word处的所有内容

[leon@localhost ~]$ string=string-hello-myname-is-hello-over
[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string#*hello}
-myname-is-hello-over

${string##*word} :在string中存储字符串上,自左而右,查找最后一次出现word,删除字符开始到此word处的所有内容

[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string#*hello}
-myname-is-hello-over
[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string##*hello}
-over

${string%word*}在string中存储的字符串上,自右而左,查找第一次出现的word,删除字符开始到此word处的所有内容

[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string%hello*}
string-hello-myname-is-

${string%%word*}在string中存储的字符串上,自右而左,查找最后一次出现的word,删除字符开始到此word处的所有内容

[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string%%hello*}
string-

3.2.2 字符串查找替换

${string/pattern/substi} :替换第一次出现的字符串

[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string/hello/hi}
string-hi-myname-is-hello-over

${sting//pattern/substi} :替换所有出现过的字符串

[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string//hello/hi}
string-hi-myname-is-hi-over
${string/pattern}
[leon@localhost ~]$ echo ${string//hello/hi}
[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string/hello}
string--myname-is-hello-over
${string//pattern}[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string//hello}
string--myname-is--over
[leon@localhost ~]$

四、流程控制

4.1 选择分支

4.1.1 条件测试

条件测试中,如果为真,则返回执行状态为0的值,否则返回执行状态为非0的值

整型测试:数值之间比较大小     字符型比较

-gt  -lt  -eq  -ge  -le    >   <  ==  !=  >=  <=  -n  -z

常用文件测试

-e    文件存在

[leon@localhost ~]$ [ -e /tmp/xxxxxxx ] 
[leon@localhost ~]$ echo $?
1

-d    文件存在且为目录

[leon@localhost ~]$ [ -d /tmp ] 
[leon@localhost ~]$ echo $?
0

-f    文件存在且为普通文件

[leon@localhost ~]$ [ -f /tmp ] 
[leon@localhost ~]$ echo $?
1

-r    文件是否具有可读权限

[leon@localhost ~]$ [  -r /root ]

[leon@localhost ~]$ echo $?

1

-w    文件是否具有可写权限

[leon@localhost ~]$ [ -w /home/leon ]
[leon@localhost ~]$ echo $?
0

-x    文件是否具有可执行权限

[leon@localhost ~]$ [ -x /home/leon ]
[leon@localhost ~]$ echo $?
0

组合条件测试 :在多个条件间实现逻辑运算

与: [ 条件一 -a 条件二 ]

    条件一 && 条件二

[leon@localhost ~]$ [ -x /home -a -r /root ]
[leon@localhost ~]$ echo $?
1

[leon@localhost ~]$ test -x /home &&  test -r /root
[leon@localhost ~]$ echo $?
1

或: [ 条件一 -o 条件二 ]

    条件一 || 条件二 

[leon@localhost ~]$ [ -x /home -o -r /root ]
[leon@localhost ~]$ echo $?
0

[leon@localhost ~]$ test -x /home ||  test -r /tmp
[leon@localhost ~]$ echo $?
0

非:[ !条件 ]

[leon@localhost ~]$ [ ! -r /home/leon ]
[leon@localhost ~]$ echo $?
1

4.1.2 if选择分支

语法: if 测试条件1;then

    选择分支1

   elif 测试条件2;then

    选择分支2

   ……

   elif 测试条件n;then

    选择分支n

   else

    分支

   fi

[leon@localhost ~]$ if true ; then echo true ;else  echo false ;fi
true[leon@localhost ~]$ 
[leon@localhost ~]$ if id test1 &>/dev/null ; then echo test1 ;elif id test2 &>/dev/null;then echo test2 ;elif id leon &>/dev/null ;then echo leon ;fi
leon
[leon@localhost ~]$ if [ $? -eq 0 ] ;then echo ture ;else echo false;fi
ture

4.1.3 case选择分支

语法:case word  in

    pattern1)

    分支1

    ;;

    pattern2)

    分支2

    ;;

    patternN)

     分支N

    ;;

    *)

      分支

    ;;

    esac

[leon@localhost ~]$ case leon in  root) id root ;; leon) echo leon ;; *) echo not this user! ;; esac
leon
[leon@localhost tmp]$ cat testCase.sh 
#!/bin/bsh
#
case $1 in
1)
 echo 1
 ;;
2)
 echo 2
 ;;
3)
 echo 3
 ;;
*)
 echo order
 ;;
esac
[leon@localhost tmp]$ chmod +x testCase.sh 
[leon@localhost tmp]$ sh testCase.sh 
order
[leon@localhost tmp]$ ./testCase.sh 1
1

4.2 循环

4.2.1 for循环

语法1: for i in  list ;do

       list

    done

语法2: for ((表达式一;条件表达式;表达式二));do

       list

    done

[leon@localhost tmp]$ for i in {1..5};do echo $i ;done
1
2
3
4
5
[leon@localhost tmp]$ for ((i=1;i<=5;i++));do echo $i ;done
1
2
3
4
5

4.2.2 while循环

语法1: while 测试条件; do

        循环体

    done
语法2: while read 变量名;do

        循环体

    done < /path/to/somefile

[leon@localhost tmp]$ cat testWhile.sh 
#!/bin/bash
#
declare -i i=1
while [ $i -le 5  ];do        #比较i和5的大小,为真则进入循环,为假则退出循环
echo $i
let i++
done
[leon@localhost tmp]$ sh  testWhile.sh
1
2
3
4
5

[leon@localhost tmp]$ cat testWhile.sh 
#!/bin/bash
#
while read userInfo;do
echo $userInfo
done < /etc/passwd
[leon@localhost tmp]$ sh testWhile.sh 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
......
openstack:x:502:502::/home/openstack:/bin/bash
[leon@localhost tmp]$

 4.2.3 until循环

语法:until 测试条件; do

        循环体

    done

[leon@vm tmp]$ cat testUntil.sh 
#!/bin/bash
#
declare -i i=5
until [ $i -lt 1 ];do        #比较i和1的大小,为假就进入循环,为真则退出循环
echo $i
let i--
done
[leon@vm tmp]$ sh testUntil.sh 
5
4
3
2
1

五、函数及返回值

语法1: function function_name {list}

语法2: function_name () {list}

[leon@vm tmp]$ cat testFunction.sh 
#!/bin/bash
#
function display {        #定义一个名为display的函数
cat << NODE

-------------------
------meau---------
1: install os
2: quit
-------------------
NODE
return 0              #退出函数并返回状态值0
echo next function_list
}
view() {
display                #调用函数
exit 1                #退出shell并返回状态值1
}
view
[leon@vm tmp]$ sh testFunction.sh 

-------------------
------meau---------
1: install os
2: quit
-------------------
[leon@vm tmp]$ echo $?
1

六、循环控制

continue : 提前进入下一轮循环

[leon@vm tmp]$ cat testContinue.sh
#/bin/bash
#
for (( i=1;i<=2;i++  )) ;do
echo outside $i
for (( n=1;n<=2;n++ ));do
echo inside $n
continue                            #直接进入下一循环
#	break
echo hello                         #这个echo语句用于没有将会执行
done
done
[leon@vm tmp]$ sh testContinue.sh
outside 1
inside 1
inside 2
outside 2
inside 1
inside 2

break  :跳出当前循环

[leon@vm tmp]$ cat testContinue.sh
#/bin/bash
#
for (( i=1;i<=2;i++  )) ;do
echo outside $i
for (( n=1;n<=2;n++ ));do
echo inside $n
#	continue
break                    #退出当前循环
echo hello
done
done
[leon@vm tmp]$ sh testContinue.sh
outside 1
inside 1
outside 2
inside 1

七、信号捕捉

信号捕捉:trap 'COMMAND;COMMAND'  SINGNAL

[leon@vm tmp]$ cat testTrap.sh 
#!/bin/bash
#
trap 'echo exit' SIGINT
ping -c 100 www.baidu.com
[leon@vm tmp]$ sh testTrap.sh            #按ctrl+c时,捕捉到信号。
PING www.a.shifen.com (180.97.33.108) 56(84) bytes of data.
64 bytes from 180.97.33.108: icmp_seq=1 ttl=128 time=29.4 ms
64 bytes from 180.97.33.108: icmp_seq=2 ttl=128 time=29.5 ms
^C
--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1278ms
rtt min/avg/max/mdev = 29.489/29.530/29.571/0.041 ms
exit                #退出脚本时执行echo语句输出

八、总结

shell编程是linux运维人员必须掌握的技能,shell不像其它C、C#、Java等高级编程语言那样有类和对象,面向对象等概念,但是shell可以有强大的命令支撑。毕竟我们是通过shell来沟通内核,不需要运行在虚拟机上。

原创文章,作者:成吉思汗,如若转载,请注明出处:http://www.178linux.com/8026

(0)
成吉思汗成吉思汗
上一篇 2015-09-22
下一篇 2015-09-22

相关推荐

  • 通过堡垒机代理SSH运行Ansible(译)

    有一种常见的网络安全模式是阻止私有网络外部对应用服务器的所有连接(指除了业务数据外其它的连接,如后台管理系统和内部业务系统。译者注),然后使用 DMZ 区域中的 堡垒机 来选择性的将到服务器的流量加入白名单。 我们有这样的一个服务器池,只允许来自特定 IP 地址的 SSH 流量。这些服务器还由 Ansible…

    Linux干货 2015-02-14
  • shell 脚本 之循环 for while until 和 软件包的管理 【上】

    shell 脚本 之循环 for while until 和 软件包的管理 【上】 循环执行     将某代码段重复运行多次     重复运行多少次:             循环次数事先已知    &nbsp…

    系统运维 2016-08-18
  • N25-Bazinga-第二周作业

    1.Linux文件管理类命令 命令 功能 命令 功能 pwd 显示当前目录 ls 显示目录下的内容 cd 改变所在目录 cat 显示文件的内容 grep 在文件中查找字符串 cp 复制文件 touch 创建文件 mv 移动文件 rm 删除文件 rmdir 删除目录 1.1 pwd命令 该命令的英文解释为print working&nbsp…

    Linux干货 2016-12-13
  • 马哥教育网络班22期第五周博客作业

    正则表达式与grep 文本编辑工具     grep:是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来;     sed :是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用;     awk…

    Linux干货 2016-10-19
  • 从shell眼中看世界–展开和引用

    这篇博客的目的在于加深对于展开和引用的理解,阐释展开和引用之间联系。 ‘ ‘ :强引用,其中的变量引用不会被替换为变量值,而保持原字符串       ” “:弱引用,其中的变量引用会被替换为变量值    如果之前对于’ …

    Linux干货 2017-04-16
  • Linux文件类型及颜色标识

    文件类型(共7种): – :普通文件 d:目录文件 (directory) c:字符设备文件 (char) b:块设备文件 (block) s:本地域套接口 (socket) p:有名管道 (pipeline) l:符号连接 (link) 关于硬链接、软连接、复制之间的区别说明: 上图中,我为photo.png这个图片文件建立了一个拷贝(phot…

    Linux干货 2016-10-16

评论列表(1条)

  • stanley
    stanley 2015-09-22 09:35

    总结的非常不错,文档功底很深