shell脚本编程总结

shell脚本编程总结

shell是什么;

Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。

实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。

Linux提供了像MicrosoftWindows那样的可视的命令输入界面--X Window的图形用户界面(GUI)。它提供了很多桌面环境系统,其操作就像Windows一样,有窗口、图标和菜单,所有的管理都是通过鼠标控制。GNOME。

shell的种类

每个Linux系统的用户可以拥有他自己的用户界面或Shell,用以满足他们自己专门的Shell需要。

同Linux本身一样,Shell也有多种不同的版本。主要有下列版本的Shell: Bourne Shell:是贝尔实验室开发的。

BASH:是GNU的Bourne Again Shell,是GNU操作系统上默认的shell。

Korn Shell:是对Bourne SHell的发展,在大部分内容上与Bourne Shell兼容。

C Shell:是SUN公司Shell的BSD版本。

Z Shell:The last shell you’ll ever need! Z是最后一个字母,也就是终极Shell。它集成了bash、ksh的重要特性,同时又增加了自己独有的特性.

我们在系统上常用的shell是 bash

既然是编程,那么编程所常有的概念,在shell中的体现是怎样的呢?

事实上编程中所用到的变量,函数,数组,字符串,条件判断, 循环结构在shell中都能体现.

shell脚本语法

 第一行必须顶格写并指明以下所使用的shell 

 #!/bin/bash

 #!/usr/bin/python 

#!/bin/tcsh

各种shell 如bash,python,tcsh任君选择使用.

定义变量

shell语言是非类型的解释型语言,强类型语言编程时需要事先声明变量,并声明其类型 shell编程中给一个变量赋值就是定义变量. 
shell的变量是无类型的,所以用户想让它当字符时就是字符,想让它当数字就是数字。 

当然,我们还可以用 declare来指定其数据类型

declare 

    -r 只读变量 =>相当于其它语言的常量吧,赋值后不能修改

    -a    数组

    -i    整型

    -f    函数 

在linux支持的所有shell中,都可以用赋值符号(=)为变量赋值. 如: 
abc=7 (不能在等号两侧留下空格 ) 
name=abc 
在变量赋值之后,只需在变量前面加一个$去引用. 
echo $abc

7

echo $name

abc 

声明只读变量方法一

[robert@ca2 CA]$ declare -r nb=100 
[robert@ca2 CA]$ nb=101 
-bash: na: readonly variable    =>当尝试改变只读变量的时候,系统会发出警告,提醒这是只读变量 

声明只读变量之方法二 将变量变成常量[只读变量] 

[robert@ca2 CA]$ readonly na=100 
[robert@ca2 CA]$ echo $na 
100 
[robert@ca2 CA]$ na=20 
-bash: na: readonly variable    =>当尝试改变只读变量的时候,系统会发出警告,提醒这是只读变量 

shell脚本之条件判断

有if语句作为条件选择分支

语法 if 条件判断;then

执行语句

elif 条件判断;then

执行语句

fi if条件判断结束符

有case作为条件选择分支 

 #!/bin/bash

switch=6

case $switch in

[0-9])

    echo $switch

    ;;

[a-z])

    echo $switch

    ;;

esac


说到if语句结构,就得提及到条件测试

命令执行作为条件测试依据

   如grep 'root' /etc/passwd  将运行命令成功与否作为判断条件

if grep 'root' /etc/passwd;then

    echo "root 用户存在"

else

     echo "root 用户不存在"

fi

shell脚本之 case选择分支

  比较运算:

   >, <, >=, <=, ==, !=

条件判断中,存在各种判断, 各种测试类型如下

  测试类型:根据比较时的操作数的类型

   整型测试:整数比较

   字符测试:字符串比较

   文件测试:判断文件的存在性及属性等  

   注意:比较运算通常只在同一种类型间进行  

   整型测试:

    -gt: 例如 [ $num1 -gt $num2 ]

    -lt:

    -ge:

    -le:

    -eq:

    -ne:  

   字符串测试:

    双目

     >: [[ "$str1" > "$str2" ]]

     <:

     >=

     <=

     ==

     !=  

    单目:

       -n String: 是否不空,不空则为真,空则为假

       -z String: 是否为空,空则为真,不空则假

bash条件测试之文件测试:  

       -a file

              True if file exists.

       -b file

              True if file exists and is a block special file.

       -c file

              True if file exists and is a character special file.

       -d file

              True if file exists and is a directory.

       -e file

              True if file exists.

       -f file

              True if file exists and is a regular file.

       -g file

              True if file exists and is set-group-id.

       -h file

              True if file exists and is a symbolic link.

       -k file

              True if file exists and its ''sticky'' bit is set.

       -p file

              True if file exists and is a named pipe (FIFO).

       -r file

              True if file exists and is readable.

       -s file

              True if file exists and has a size greater than zero.

       -t fd True if file descriptor fd is open and refers to a terminal.

       -u file

              True if file exists and its set-user-id bit is set.

       -w file

              True if file exists and is writable.

       -x file

              True if file exists and is executable.

       -O file

              True if file exists and is owned by the effective user id.

       -G file

              True if file exists and is owned by the effective group id.

       -L file

              True if file exists and is a symbolic link.

       -S file

              True if file exists and is a socket.

       -N file

              True if file exists and has been modified since it was last read.

       file1 -nt file2

              True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.

       file1 -ot file2

              True if file1 is older than file2, or if file2 exists and file1 does not.

       file1 -ef file2

              True if file1 and file2 refer to the same device and inode numbers.

       -o optname

              True if shell option optname is enabled. See the list of options under the description of the -o option to the set builtin

              below.  

          -a FILE

          -e FILE: 存在则为真;否则则为假;

          -f FILE: 存在并且为普通文件,则为真;否则为假;

          -d FILE: 存在并且为目录文件,则为真;否则为假;

          -L/-h FILE: 存在并且为符号链接文件,则为真;否则为假;

          -b: 块设备

          -c: 字符设备

          -S: 套接字文件

          -p: 命名管道  

          -s FILE: 存在并且为非空文件则为值,否则为假;  

          -r FILE

          -w FILE

          -x FILE  

          file1 -nt file2: file1的mtime新于file2则为真,否则为假;

          file1 -ot file2:file1的mtime旧于file2则为真,否则为假; 

shell脚本之for in 循环

格式 for 变量 in 集合;do 语句体 ; done 循环结束标识

详细案例如下

declare -i sum=0 

for i in {1..9};do

     let sum+=$i         //sum=$[$sum+$i] 中括号相加

done

echo $sum        

let计算

shell脚本之for 循环

#!/bin/bash

for ((i=0;$i<10;i++));do

    echo $i

done  

shell脚本之while 循环

num=0

while true ;do

    let num++

    if [ $num -gt 10 ];then

        break

    fi

done

echo $num

shell脚本之until 循环 ==>与while循环不同的是,until的条件判断中,条件不成立,循环会继续进行

num=0

until [ $num -gt 10 ];do

    let num++

done

echo $num

shell 脚本之函数使用

function test {

    echo "$1 do you want test function"

}

test 'robert'

shell脚本之数组

 数组是编程中,存储控制数据非常重要的一个手段和方式,但遗憾的是 linux的shell只支持一维数组

数组其实也是一种变量,不同的是,这个特殊类型的变量内,还可以存其它的变量.

数组的使用

  数组名+索引

   数组元素  

  索引的表示方式:

   数字索引:a[index]

    a[0], a[1]  

   bash 4.0的关联数组

    a[hello], a[hi]  

   declare -a    索引数组

                 -A     关联数组

  支持稀疏格式: 

 数组的赋值:

  一次对一个元素赋值:

 a[0]=0

 a[1]=1

 a[2]=2 

 a[3]=3 

  直接赋值:

   arr=(0 1 2 3)

  按索引进行赋值:

   a=([0]=0 [3]=3 [2]=2 [1]=1) 

  用户输入:

   read -a arr 用户输入的方式生成数组 

 数组的访问:

  用索引访问:

   ARRAY[index]

如 a=([0]=0 [3]=3 [2]=2 [1]=1) 

echo a[0]访问索引为0的数组

0 ==>结果为0

 数组的长度: 

[robert@ca2 ~]$ array=([0]=0 [3]=3 [2]=2 [1]=1) 
[robert@ca2 ~]$ echo ${#array[@]} 

 从数组中挑选某元素:

  ${ARRAY[@]:offset:number}

   切片:

    offset: 偏移的元素个数

    number: 取出的元素的个数

[robert@ca2 ~]$ array=([0]=0 [3]=3 [2]=2 [1]=1) 

[robert@ca2 ~]$ echo ${array[@]:1:2}  
1 2

  ${ARRAY[@]:offset}:取出偏移量后的所有元素

[robert@ca2 ~]$ echo ${array[@]:1} 
1 2 3

  ${ARRAY[@]}: 取出所有元素

[robert@ca2 ~]$ echo ${array[@]} 
0 1 2 3

  使用@和*的不同

  $@: 每个参数是一个独立的串

  $*: 所有参数是一个串

数组如果想作为对数传入给函数使用,怎么办呢? 

#!/bin/bash  

function myarr {

#echo $@

#exit 0

    newarr=(echo "$@")    接收时转化为数组

    echo ${newarr[@]}

}

myarray=(12 23 34 45)

myarr ${myarray[@]}     ==>注,为函数传递数组作为变量,需要注意,要将其转化为N个参数传入

在编程中,字符串的操作是相当频繁常用的

字符串

字符串切片: 
${string:offset:length}     从左向右取,依稀量,加长度, 如果只指定偏移量,则偏移后,取所有字串 
取尾部的指定个数的字符: 
${string: -length}         加个 " - " 号,则是从右向左取 
取子串:基于模式 
${variable#*word}:在variable中存储字串上,自左而右,查找第一次出现word,删除字符开始至此word处的所有内容;  

[root@localhost ~]# url=www.baidu.com 
[root@localhost ~]# echo $url 
www.baidu.com 
[root@localhost ~]# echo ${url#*.}    从左到右,取第一次出现的.号,并从左开始第一个字符删除到第一次出现的字符,    
baidu.com

[root@localhost ~]# echo ${url##*.} 再加一个# 是贪婪模式,找到从左到右,最后一次出现的 . 并从头到 . 删除
com


${variable##*word}:在variable中存储字串上,自左而右,查找最后一次出现word,删除字符开始至此word处的所有内容; 
file='/var/log/messages' 
${file#*/}: 返回的结果是var/log/messages 
${file##*/}: 返回messages  
${variable%word*}: 在variable中存储字串上,自右而左,查找第一次出现word,删除此word处至字串尾部的所有内容; 
${variable%%world*}:在variable中存储字串上,自右而左,查找最后一次出现word,删除此word处至字串尾部的所有内容; 
file='/var/log/messages' 
${file%*/}: 返回的结果是/var/log 
${file%%*/}: 返回结果为空  
phonenumber='010-110-8' 
${phonenumber%%-*} 
${phonenumber##*-}  
url="http://www.magedu.com:80" 

  遍历访问一个字符串(默认是以空格分开的,当字符串是由其他字符分隔时可以参考 2)
#!/bin/bash
str="a --m"
for i in $str
do
    echo $i
done


array

声明数组 myarray=(1 2 3 ) 
打印数组 echo ${myarray[@]} 
1 2 3

访问数组的长度   ${#myarray[@]} 

[root@localhost ~]# echo ${#myarray[@]} 
3

#直接输出的是数组的第一个元素
echo $array

#用下标的方式访问数组元素
echo ${array[1]}

#输出这个数组
echo ${array[@]}

#输出数组中下标为3的元素的长度
echo ${#array[3]}

#输出数组中下标 为1到3的元素
echo ${array[@]:1:3}

#输出数组中下标大于2的元素
echo ${array[@]:2}

#输出数组中下标小于2的元素
echo ${array[@]::2}

字符串

字符串切片: 
${string:offset:length}     从左向右取,依稀量,加长度, 如果只指定偏移量,则偏移后,取所有字串

取尾部的指定个数的字符: 
${string: -length}         加个 " - " 号,则是从右向左取

取子串:基于模式 
${variable#*word}:在variable中存储字串上,自左而右,查找第一次出现word,删除字符开始至此word处的所有内容; 

[root@localhost ~]# url=www.baidu.com 
[root@localhost ~]# echo $url 
www.baidu.com 
[root@localhost ~]# echo ${url#*.}    从左到右,取第一次出现的.号,并从左开始第一个字符删除到第一次出现的字符,    
baidu.com

[root@localhost ~]# echo ${url##*.} 再加一个# 是贪婪模式,找到从左到右,最后一次出现的 . 并从头到 . 删除
com


${variable##*word}:在variable中存储字串上,自左而右,查找最后一次出现word,删除字符开始至此word处的所有内容; 
file='/var/log/messages' 
${file#*/}: 返回的结果是var/log/messages 
${file##*/}: 返回messages 

${variable%word*}: 在variable中存储字串上,自右而左,查找第一次出现word,删除此word处至字串尾部的所有内容; 
${variable%%world*}:在variable中存储字串上,自右而左,查找最后一次出现word,删除此word处至字串尾部的所有内容; 
file='/var/log/messages' 
${file%*/}: 返回的结果是/var/log 
${file%%*/}: 返回结果为空 

phonenumber='010-110-8' 
${phonenumber%%-*} 
${phonenumber##*-} 

url="http://www.magedu.com:80"

  遍历访问一个字符串(默认是以空格分开的,当字符串是由其他字符分隔时可以参考 2)
#!/bin/bash
str="a --m"
for i in $str
do
    echo $i
done

1.长度

[root@localhost ~]$ test='I love china'
[root@localhost ~]$ echo ${#test}
12

${#变量名}得到字符串长度

 

2.截取字串

[root@localhost ~]$ test='I love china'
[root@localhost ~]$ echo ${test:5}     
e china
[root@localhost ~]$ echo ${test:5:10} 
e china

${变量名:起始:长度}得到子字符串

 

3.字符串删除

[root@localhost ~]$ test='//tmp/boot.ini'
[root@localhost ~]$ echo ${test#/}
/tmp/boot.ini
[root@localhost ~]$ echo ${test#*/}
/tmp/boot.ini
[root@localhost ~]$ echo ${test##*/}
boot.ini

[root@localhost ~]$ echo ${test%/*} 

c:/windows
[root@localhost ~]$ echo ${test%%/*}

${变量名#substring正则表达式}从字符串开头开始配备substring,删除匹配上的表达式。

${变量名%substring正则表达式}从字符串结尾开始配备substring,删除匹配上的表达式。

注意:${test##*/},${test%/*} 分别是得到文件名,或者目录地址最简单方法。

4.字符串替换

[chengmo@localhost ~]$ test='/tmp/boot.ini'
[chengmo@localhost ~]$ echo ${test/\//\\}
/tmp/boot.ini

[chengmo@localhost ~]$ echo ${test//\//\\}
/tmp/boot.ini


你可能感兴趣的:(shell,总结,脚本编程)