认识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

相关推荐

  • linux权限管理

          今天来讲讲linux里面权限的问题,在linux系统中,有这么几类权限,r,w,x,s,t这么几类权限,系统中为什么要有权限这个东西呢,linux一切皆文件,有些文件不想让某些人看到,那么这个时候就需要设置文件的访问的权限了,文件的拥有者一般都是有权力修改删除文件的,但拥有者以外的人未必就能删除修…

    Linux干货 2016-08-04
  • 创建LVM分区实例

                         内容概述   LVM逻辑卷的定义                       &nbsp…

    2017-06-25
  • 用户和组管理类命令的使用

    1.列出当前系统所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示以此即可; who | cut -d' ' -f1 | sort | uniq 2.取出最后登录到当前系统的用户的相关信息; who | head&nb…

    Linux干货 2016-11-21
  • Hadoop hdfs 分布式文件系统

    Hadoop简介:一个分布式系统基础架构,由Apache基金会开发。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力高速运算和存储。Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有着高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件…

    Linux干货 2015-08-05
  • 马哥教育网络班21期+第15周课程练习

    1、总结sed和awk的详细用法; sed的详细用法 awk的详细用法 2、删除/boot/grub/grub.conf文件中所有行的行首的空白字符; # sed 's/^[[:space:]]*//' /boot/grub/grub.conf 3、删除/etc/fstab文件中所有以#开头,后跟至少一个空白…

    Linux干货 2016-11-14
  • linux 入门基础 (二)

    主要内容包含有 文件查找、压缩和正则表达式,以及包是管理和安装。

    2017-09-10

评论列表(1条)

  • stanley
    stanley 2015-09-22 09:35

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