shell编程基础篇

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell编程基础篇相关的知识,希望对你有一定的参考价值。

重点注意,我们这里介绍的是CentOS 6.7 版本的Linux


一、shell的介绍

 (1)什么是shell?

     技术图片
  shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出的结果,输出到屏幕返回给用户。这种对话方式可以是交互式的(从键盘输入,立刻得到shell的回应),或者非交互式的。Shell:是一门弱类型(语法叫宽松)的语言较为通用的shell有bash shell。shell脚本语言的种类也比较多:Bourne shell (包括:sh,ksh,and bash)、C Shell (包括:csh and tcsh)。当然我们这里主要说的是bash shell!!!!!

 (2)shell的编写规范

   - 脚本的开头第一行为:#!/bin/bash 或者 #!/bin/sh。这是因为#!又称为幻数,在执行bash脚本的时候,内核会根据它来确定该用哪一个程序来解释脚本中的内容,这一行必须在脚本的顶端的第一行。其实bash和sh是一个文件,只不过在Linux中/bin/sh是一个链接文件实际的指向为/bin/bash。
   - 如果在脚本的第一行没有指定解释器,在运行的时候需要使用bash命令执行。
   - 开头加入版权、作者等信息(只是一个建议而已)
   - 脚本中尽量不要使用中文
   - 脚本名称尽量以.sh结尾
   - 尽量添加多的注释,这样对调试和其他人使用脚本都有帮助。

 (3)shell的注释

   - 单行注释:“#”
   - 多行注释:“:<<! !:”

 (4)脚本的执行?

   在Linux下执行shell有三种方式:
   - bash / sh 执行shell脚本
   - path/script.sh 直接执行脚本(脚本必须是可执行文件,并且首行有解释器标识)
   - source script.sh或者. script.sh 这种方式可以将自身脚本中的变量的值或者函数等的返回值传递到父shell中执行。(当前操作的shell(父)---编写的脚本执行(子)),也相当于父shell将子shell的脚本中命令读取到自己的shell中然后执行。

二、shell中的变量

 (1)shell的变量介绍

  shell中的变量分为两类:环境变量(全局变量)和局部变量
   环境变量:在创建他们的shell以及派生出来的任意子进程的shell中均可以使用。
   局部变量:只能在创建他们的shell函数或者脚本中使用。

 (2)环境变量

   用于定义shell的运行环境,保证shell的正确执行。所有的环境变量都是系统的全局变量可以用于所有子进程中,包括编辑器、shell脚本和各类应用。
   例:

#声明
        export 变量名 = 变量的值
        变量名=变量的值;export 变量名
        declare -x 变量名=变量的值
#系统内置的环境变量介绍:
$HOME       用户的家目录
$USER        当前用户
$UID         当前用户的uid
$SHELL       当前用户使用的shell
$HISTISZE     记录在命令行历史文件中的命令行数
$PATH        执行命令时寻找的目录
$PWD        当前用户的家目录
$PS1          用户登录的环境变量  [[email protected] ~]
$TMOUT       用户登录的超时时间
#显示和取消环境变量
显示:echo $变量
set和env 显示所有的环境变量。
取消:unset 变量名。
readonly:设置只读变量

 (3)局部变量

   局部变量也成为本地变量,在用户当前的shell中使用,如果退出shell,则失效。
  例:

#声明:
变量名=value(数字、字母、下划线组成)

这里需要介绍一下Linux下的双引号、单引号和不加引号的区别:
技术图片
由上面的例子可以看出:
单引号:所见即所得,单引号内的内容原样输出。
双引号:如果内容中有变量等,会将变量解析出来,然后将最终的结果打印
不加引号:把内容输出出来,如果有连续的空格会将空格合并为一个空格,然后将变量等解析出来在输出。
反引号:把字符串当做命令去执行。
技术图片
注意:一般的在使用命令的时候,变量的引用尽量不要加引号或双引号。但是在做字符串判断的时候一般的都需要加上引号。

 (4)特殊变量

#介绍
$0:表示获取当前脚本的脚本名、
$n:获取当前执行的shell脚本的第n个参数,n=1..9,如果n大于10,用${10}
$#:获取当前shell命令行中参数的个数
$*:表示参数列表
[email protected]:表示参数列表
$$:获取当前shell的进程号
$!:执行上一个指令的PID
$?:获取执行的上一个指令的返回值(0表示成功,非零表示失败)
$_:在此之前执行的命令或脚本的最后一个参数

具体的小编在这里给大家补充两点:
   - $*和[email protected]的区别
技术图片
大家可以运行上面的脚本并传入参数,看看具体如何打印的,就大概明白两者的区别了。
   - $?返回值得介绍(有助于错误排查):

            0:表示执行成功
            2:权限拒绝
            1~125:表示运行失败,脚本命令,系统命令,错误或者参数传递错误
            126:找到该命令,但是无法执行
            127:未找到该命令
            大于128:命令被系统强制停止

三、shell变量的进阶操作

(1)shell变量的计算

   好的shell脚本,变量的计算显然是离不开的,可以使用(())、let、expr、bc、$[]变量进行计算,这里给大家总结几个常用的。

   (()):

    只能用于整数计算。常用,效率高。

#用法
a=$((1+1));   需要使用$进行修饰
((a=1+1))   此种方式不需要用$修饰
a=((3>1))    也可以写入比较,正确返回1,错误返回0
#实现简单的计算器:
#!/bin/sh
read -p "Please input first num:" num1
read -p "Please input operators:" operators
read -p "Please input second num:" num2
sum=$(($num1$operators$num2))
echo "$num1 $operators $num2 = $sum"

   let:

    用作简单的整数计算,let赋值表达式。
#例:

[[email protected] zy]# i=2
[[email protected] zy]# i=i+8 #表示字符串的拼接
[[email protected] zy]# echo $i #打印i+8
[[email protected] zy]# i=2
[[email protected] zy]# let i=i+8 #表示数值计算
[[email protected] zy]# echo $i #打印10

   bc:

    可以实现整数、小数的运算,接受标准输入。

[[email protected] zy]# i=2
[[email protected] zy]# echo "$i+2.4"|bc #打印4.4

#实现1+2…10的计算
#!/bin/sh
str=""
for i in `seq 10` 
  do
    if [ $i -eq 10 ];then
      str=$str$i
    else
      str=$str$i"+"
    fi
  done
sum=`echo "$str"|bc`
echo "$str=$sum"

#保留小数

[[email protected] zy]# echo "scale=2;3.14/2.1"|bc #保留两位小数

   $[]:

    a=$[1+1],与(())类似,但是[]不能讲变量提取到[]中。
技术图片

(2)变量子串的常见操作

#子串的操作
${#string}      返回string这个变量的长度
${strting:position} 在变量string中从position开始提取子串(从0开始,取到结尾)
${string:pos:len}   在变量string中从pos开始提取子串,提取长度为len
${string#sub}   在变量string中从头开始,删除sub匹配的子串
${string%sub}   在变量string中从末尾开始,删除sub匹配的子串
${string/old/new}   在变量string中将old内容,替换成new(只替换第一个找到的)
${string//old/new}  在变量string中将old内容,替换成new(替换所有找到的内容)
${value:=word}  给变量赋默认值,LOD=${value:=word}, $LOD的值为word
${value:index:len}  从index位置开始取值,向后取len长度
#变量的替换
${value:-word}  当value定义或者为空时,返回后面的值,当value已经有值了就返回value的值, 只是针对返回值,value本身仍然没有值    
#例:
result=${value:-word}
echo $result    #打印word
echo $value   #打印空

${value:=word}  当value定义或者为空时,返回后面的值, value的值也会改变,当value已经有值了就返回value的值, 
#例:
result=${value:=word}
echo $result    #打印word
echo $value   #打印word

${value:?”not default”} 如果变量名存在且非空,则返回变量的值,否则显示“变量名:message“,并退出当前脚本    
#例:
[[email protected] zy]# ${key:?"not default"} #打印 -bash: key: not default

${value:+word}  如果变量存在且不为空,则返回后面的值,否则返回null。用于测试变量是否存在  
#例:
[[email protected] zy]# echo ${result:+word}  #打印:word(已定义)
[[email protected] zy]# echo ${key:+word} #打印 空 (未定义)

${result-value} 与${value:-word}相同   

这里给大家介绍一个具体的例子看看,变量操作的重要意义:

#将某目录下的所有.jpg的文件改成,以.JPG的结尾
#方法一:
for i in `ls *.jpg`;do mv $i ${i/%jpg/JPG} ; done;
#方法二:
rename .jpg .JPG *
#计算变量的长度
#方法一:
[[email protected] zy]# echo ${#chars}
#方法二:
[[email protected] zy]# echo $chars|wc –c  #会多打印末尾的换行
#方法三:
[[email protected] zy]# echo $(expr length "$chars")
#方法四:
echo $value|awk -F’’ ‘BEFORE{count=0}  {count++}  END{print count}’

看似不使用变量操作,就可以使用命令解决我们的问题,但是执行的效率呢?
我们可以在命令前加上time 查看命令执行的时间:
[[email protected] ~]# time for i in seq 1111 ;do count=${#chars};done;
技术图片
同样的可以查看上面所有的方法的执行时间,一对比,就只到变量操作的强大体现在哪里。这里小编给大家总结一下(以前三种方法为例):方法一>方法三>方法二 #最终使用内置的功能效率最高

四、shell中通用常用命令介绍

(1)echo命令

   对于这个命令大家可能熟悉的不能再熟悉了,将指定内容显示到标准输出。
 例:

[[email protected] my_test]# echo "abc" #会打印 abc
[[email protected] my_test]# echo -n "abc abc" #会打印 abc abc
[[email protected] my_test]# echo -e "abc abc" #会打印 abc abc
[[email protected] my_test]# echo -n "abc" #默认的echo命令是打印之后换行,-n表示不换行

(2)eval命令

   读入参数,将他们组成一个新命令执行

[[email protected] my_test]# eval "echo " "1" #打印1

(3)exec命令

   当shell执行到exec语句时,不会去创建新的子进程,而是转去执行命令,当指定的命令执行完成后,shell就结束了,所以exec后的命令不会执行。

#脚本
#!/bin/sh
echo "before exec"
exec echo "exec run"
echo "after exec"

结果exec 语句之后的命令就不会执行了,而且退出了当前的shell

(4)export命令

   将申明的变量导出,成为全局变量。

(5)read命令

   从标准输出中读取字符串,传递给变量.

#介绍:
-p  设置提示信息,例:read –p “请输入:” value
-t time(second) ,设置超时时间。例:read –t 3 –p“请输入胡” value

(6)shift命令

   shift语句按如下方式重命名所有的位置变量,如,$2变成$1,$3变成$2…,即在程序中每使用一次shift命令,都使得所有的位置信息依次向左移动一个位置。$#也会依次减少,直到为0
 例:

#!/bin/sh
# script-name : test.sh
echo $# 
shift 
echo $# 
shift 
echo $# 
shift 

[[email protected] my_test]#sh test.sh 1 2 3 #最终会打印 3 2 1

(7)exit命令

   表示退出当前的shell脚本,后面可接参数,0:表示正常退出,非零表示异常退出。

以上是关于shell编程基础篇的主要内容,如果未能解决你的问题,请参考以下文章

spark 深入学习 05RDD编程之旅基础篇02-Spaek shell

shell 脚本编程基础篇

Shell编程基础篇-上

shell编程基础篇

Shell脚本编程——基础篇

Shell编程基础篇-上