Linux~之三

这篇内容包括:shell脚本基础,变量, 配置文件, 算术运算, 条件测试, 退出状态码,test等等


shell脚本:文本文件(命令的堆积)

     shabang:
            #!/bin/bash
            #!/usr/bin/python

            #!/usr/bin/perl

        exit 脚本执行到exit 就退出,当然exit [n] 同时还能退出示指定返回值      

        运行脚本
                1、给予执行权限,通过具体的文件路径指定文件执行;
                2、直接运行解释器,将脚本作为解释器程序的参数运行;
                shell编程:过程式、解释执行
                编程语言的基本结构:
                    数据存储:变量、数组
                    表达式

                    语句

        创建shell脚本:

            1)使用文本编辑器来创建文本文件

                      第一行必须有shell声明:#!(#!/bin/bash)

                       添加注释:                     以#开头   

            2)运行脚本

                        给脚本添加执行权限

                        直接运行解释器,也就是脚本文件

          脚本规范:

                    Linux~之三_第1张图片

 脚本调试:

   Linux~之三_第2张图片

变量   

    bash中变量的种类

      本地变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,

包括当前shell的子shell进程均无效;

      环境变量:对当前shell及期子shell都有效,可使用set、env查看
                 export 本地变量名
                 export 变量名=值
                 若修改环境变量的值 ,可直接变量名=值而不再需要加export
      局部变量:只对当前shell有效 ,可使用set查看

      位置变量:$1, $2, ...来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数;

                在SHELL中位置变量一般允许$0-$9这10个位置变量,其中$0代表程序本身,

                $1-$9代表第一到第九个参数。10个以上可以使用${n}。

      特殊变量:$?, $0, $*, $@, $#


      本地变量赋值:name='value'
            可以使用引用:
                value:
                   (1) 可以是直接字串; name="username"
                   (2) 变量引用:name="$username"
                   (3) 命令引用:name=`COMMAND`, name=$(COMMAND)  

      环境变量声明、赋值
                    export name=VALUE

                    declare -x name=VALUE

             bash内建的环境变量:
                    1.HOME
                       当前用户的主文件夹, 普通用户:/home/用户名  root: /root
                    2.SHELL
                       默认是/bin/bash
                    3.HISTSIZE
                       历史命令,记录总条数
                    4.MAIL
                       邮箱
                    5.PATH
                       执行查找的路径,目录间用冒号分割(:)
                    6.LANG
                       编码
                    7.RANDOM
                       随机数0~32767
                       echo $RANDOM

                       声明产生0~9随机数:declare -i number=$RANDOM*10/32768;

                       echo $[$RANDOM%50+1] //显示1到50 随机数

          注意:子进程紧会继承父进程的环境变量,子进程不会继承父进程的自定义变量,

需要在父进程export才能使用

                 环境变量相当于全局变量,自定义变量相当于局部变量。


       bash的配置文件

                按生效范围划分,存在两类:
                    全局配置:
                            /etc/profile
                            /etc/profile.d/*.sh
                            /etc/bashrc
                    个人配置:
                            ~/.bash_profile
                            ~/.bashrc

                    按功能划分,存在两类:
                            profile类:为交互式登录的shell提供配置
                    全局:/etc/profile, /etc/profile.d/*.sh
                    个人:~/.bash_profile
                    功用:
                            (1) 用于定义环境变量;
                            (2) 运行命令或脚本;

            bashrc类:为非交互式登录的shell提供配置
                全局:/etc/bashrc
                个人:~/.bashrc

                功用:
                    (1) 定义命令别名;
                    (2) 定义本地变量;


          位置变量:在脚本代码中调用通过命令行传递给脚本的参数

                $1, $2, ...:对应第1、第2等参数,shift [n]换位置
                $0: 命令本身
                $*: 传递给脚本的所有参数,全部参数合为一个字符串
                $@: 传递给脚本的所有参数,每个参数为独立字符串
                $#: 传递给脚本的参数的个数
                $@ $* 只在被双引号包起来的时候才会有差异
                set -- 清空所有位置变量

         进程使用退出状态来报告成功或失败
                0  代表成功,1-255代表失败
                $? 变量保存最近的命令退出状态
         例如

                ping -c1 -W1 hostdown &> /dev/null   

                #  -c1 :表示ping的次数   -W1:表示执行的时间,以秒为单位(执行1秒)

                echo $?  # 查看返回值   0表示正常,非0异常

        变量引用

                $name, ${name}

                " ":弱引用,其中的变量引用会被替换为变量值;

                 ' ':强引用,其中的变量引用不会被替换为变量值,而保持原字符串;           

           例如:
                    #!/bin/bash
                    # 对变量赋值:
                    a="hello world"  #等号两边均不能有空格存在
                    # 打印变量a的值:
                    echo -e "A is: $a\n"

     备注:

         bash中变量的赋值=号两边都不能有空格,有时候变量会和其他文字混淆,

这时候就用{}来说明下


     例如:num=1
           echo "this is the $numst"

                    #本来我们是要调用$num的,这样写linux就不认识了,改为${unm}st

           

       显示所有环境变量

                env
                printenv
                export
                declare -x
                set

       删除变量

                unset name

      变量的累加
                PATH=$PATH:/home/dmtsai/bin
                PATH="$PATH":/home/dmtsai/bin
                PATH={$PATH}:/home/dmtsai/bin

       只读变量:只能声明,但不能修改和删除
       声明只读变量
                readonly name
                declare -r name
       查看只读变量
                readonly –p
       变量命名法则
                1、不能使程序中的保留字:例如if, for;
                2、只能使用数字、字母及下划线,且不能以数字开头;
                3、见名知义,
       退出状态码:

             Linux~之三_第3张图片

算术运算:

            Linux~之三_第4张图片


        赋值   

              +=    -=    *=    /=    %=       

       例如:Linux~之三_第5张图片    


逻辑运算:&&(与)    ||(或)    !(非)

                            

           Linux~之三_第6张图片    Linux~之三_第7张图片


短路运算:
                与:
                    第一个为0,结果必定为0;
                    第一个为1,第二个必须要参与运算;
                或:
                    第一个为1,结果必定为1;
                    第一个为0,第二个必须要参与运算

                    cmd1 && cmd2
                    如果cmd1为假,cmd2不需要执行,反之cmd1为真,需要cmd2执行

                    cmd1 || cmd2

                    如果cmd1为真,cmd2不需要执行,反之cmd1为假,需要cmd2执行

条件测试:

            &&:    表示前面的命令执行成功才执行后面的命令

            ||:    表示前面的命令执行失败才执行后面的命令

        举例说明

            1)备份复制

    mkdir backupdir && cp /etc/passwd backupdir      

   #意思是说创建目录backupdir,复制passwd到改目录,如果这个目录本来 就存在,则不执行复制。

            2)创建用户

     UserName=liuchan; id $UserName &> /dev/null && echo "$UserName is already exist"|| (useradd $UserName;echo"$UserName created" & )  


        #第一个下划线是设置变量   

        #第二个下划线说的是用id查看这个用户存不存在  

        #第三个下划线说的是上个命令执行成功表示这个用户存在,则显示这段话

        #第四个下划线说的是id这条命令执行失败,就是说这个用户不存在,则执行它创建用户    

 test的用法  [ ]

   数值比较

      == 表示字符串是否相同

      n1 -eq  n2   表示两个整数是否相等(可以为负,不能为浮点数)(等于则为真)
      n1 -gt   n2  大于左边的数是否大于右边的数       (大于则为真)
      n1 -ge   n2  大于等于                          (大于等于则为真)   
      n1 -lt   n2  小于                               (小于则为真)
      n1 -le   n2  小于等于                          (小于等于则为真)
      n1 -ne  n2   不等于                            (不等于则为真)

      -v 变量名  判断一个变量是否被定义    

        例子

                 num1=100
                 num2=100
            if test $[num1] -eq $[num2]
                then
            echo '两个数相等!'
                else
            echo '两个数不相等!'

            fi

            输出结果是:两个数相等

        字符串测试

               == 是否相同
              != 或 <> 表示是否不同
              ~=  左侧字符串是否能够被右侧的PATTERN所匹配
                    [[ ab =~ a ]]
               > 是否大于
                    [[ b > a ]] 表示在默认编码表中的顺序,排后面的是较大的。
              < 是否小于

                    [[ a < b ]]

              -z "String" 判断字符串是否为空,为空时为真

              -n "String" 判断字符串是否为非空,为非空时为真

          注意:

              字符串比较大于小于号必须转义,就是加反斜线

              字符串比较是按ASCII码表,大写字母比小写字母的值小

              例子:

                        num1="ru1noob"
                        num2="runoob"
                        if test $num1 = $num2
                        then
                            echo '两个字符串相等!'
                        else
                            echo '两个字符串不相等!'

                        fi

                           输出结果:两个字符串不相等

            文件判断:                   

-b file file存在,并且为块特殊文件,则为真
-c file file存在,并且为字符特殊文件,则为真
-d file file存在,并且为目录,则为真
-e file file存在,则为真
-f file file存在,并且为常规文件,则为真
-g file file存在,并且设置了文件的 SGID 位,则为真
-G file file存在,并且为组所有,则为真
-r file file存在,并且有读权限,则为真
-s file file存在,并且长度大于0,则为真
-w file file存在,并且有写权限,则为真
-x file file存在,并且有执行权限,则为真

    

举例(转)

     1、  利用 test 来帮我们写几个简单的例子。首先,判断一下,让使用者输入一个档名,我们判断:

  1. 这个文件是否存在,若不存在则给予一个『Filename does not exist』的信息,并中断程序;
  2. 若这个文件存在,则判断他是个文件或目录,结果输出『Filename is regular file』或 『Filename is directory』
  3. 判断一下,运行者的身份对这个文件或目录所拥有的权限,并输出权限数据
  1. #!/bin/bash  
  2. echo -e "pls input a filename, I will check the filename;s type and \  
  3. permission.\n\n"  
  4. read -p "input a filename: " filename  
  5. test ! -e $filename && echo "the fils is not existed!" && exit 0  
  6. test -f $filename && filetype="filename is regular file."  
  7. test -d $filename && filetype="filename is directory."  
  8. test -r $filename && perm="readable"  
  9. test -w $filename && perm="writable"  
  10. test -x $filename && perm="executable"  
  11.   
  12. echo "the filename: $filename is a $filetype"  
  13. echo "and the permissions are: $perm" 
   

2、检查目录

       -d测试会检查指定的文件名是否在系统上以目录形式存在。当写文件到某个目录之前,或者是将文件放

置到某个目录位置之前时,这会非常有用。

               
  1. #!/bin/bash   
  2. if [ -d $HOME ]   
  3. then   
  4. echo "Your HOME directory exists"   
  5. cd $HOME   
  6. ls -a   
  7. else   
  8. echo "There is a problem with your HOME directory"   
  9. fi 

          上面代码使用了-d测试条件来检查用户的$HOME目录是否存在。如果它存在的话,它将继续使用cd命令来切到$HOME目录并进行显示目录下的文件


        

3、检查对象是否存在

      -e比较允许你在脚本中使用对象前检查文件或目录对象是否存在:


  1. #!/bin/bash   
  2. # checking if a directory exists   
  3. if [ -e $HOME ]   
  4. then   
  5. echo "OK on the directory, now to check the file"   
  6. # checking if a file exists   
  7. if [ -e $HOME/testing ]   
  8. then   
  9. # the file exists, append date to it   
  10. echo "Appending date to existing file"   
  11. date >> $HOME/testing   
  12. else   
  13. # the file does not exist, create a new file   
  14. echo "Creating new file"   
  15. echo > $HOME/testing   
  16. fi   
  17. else   
  18. echo "Sorry, you do not have a HOME directory"   
  19. fi  


4、检查文件

      -e比较适用于文件和目录。但要确定指定的对象是个文件,你必须用-f比较: 


  1. #!/bin/bash   
  2. # check if a file   
  3. if [ -e $HOME ]   
  4. then   
  5. echo "The object exists, is it a file?"   
  6. if [ -f $HOME ]   
  7. then   
  8. echo "Yes, it is a file!"   
  9. else   
  10. echo "No, it is not a file!"   
  11. if [ -f $HOME/.bash_history ]   
  12. then   
  13. echo "But this is a file!"   
  14. fi   
  15. fi   
  16. else   
  17. echo "Sorry, the object does not exist"   
  18. fi 
    

5、检查是否可读

在尝试从文件中读取数据之前,最好先测试一下是否能读文件。可以用-r测试。


6、检查空文件

用-s来检查文件是否为空,尤其是在你要删除文件时。当-s比较成功时要特别小心,它说明文件中有数据。


7、检查是否可写

-w比较用来判断你是否对文件有可写权限。


8、检查是否可执行

-x比较是一个简便的断判断你对某个特定文件是否有执行权限的方法。虽然可能大多数命令用不到它,但如果你

要在shell中运行大量脚本,它可能很方便。


9、检查所属关系

-O比较允许你轻松地测试你是否是文件的属主。


10、检查默认属组关系

-G比较会检查文件的默认组,如果它匹配了用户的默认组,那就通过了



       实验:

         编写脚本/root/bin/argsnum.sh,接受一个文件路径作为参数;如果参数个数小于1,则提示用户“至少应该给一个参数”,并立即  退 出;如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数
                                #!/bin/bash
                                [ $# -eq 0 ] &&  echo 至少应该给一个参数 && exit 1
                                grep "^[[:space:]]*$" $1  |wc -l

       

         写一个创建用户的脚本,会询问用户用户名及密码,要求密码输入过程不可见
                方法一:
                    #!/bin/bash
                    read -p "Please Enter your username: " name
                    echo -n "Please Enter the password for $name: "
                    stty -echo
                    read password
                    stty echo
                    echo
                    useradd $name
                    echo $password |passwd --stdin $name &> /dev/null
                    echo "$name created"


                方法二:
                     #!/bin/bash
                     read -p "Please Enter your username: " name
                     read -sp "Please Enter the password for $name: " password
                     echo
                     useradd $name
                     echo $password |passwd --stdin $name &> /dev/null
                     echo "$name created"



转译
        \ 完全单个转译
       ''  完全范围转译
       ""  不完全范围转译对于以下四个符号不可转译
             不能去! \  $  `
       A="my hostname is $(hostname)"
          [root@instructor_v7 app]# echo $A
           my hostname is instructor.lisi.com



登录式shell 与 非登录式shell

    登录式shell
        登录图型化
        登录文本tty终端
        远程登录如ssh,telnet
         su -

   执行顺序:

     /etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc


  非登录式
       su  
       执行shell脚本
       在已登录的图型介面打开终端


    执行顺序:
        ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

      source 和 . 在当前shell下执行来自文件的命令。

      使用脚本执行 是在子shell下执行命令,那么父shell是无法继承来自脚本中的变量


备注:一般我们经常使用的自定义环境变量脚本放在profile.d下

            shell脚本基础练习题---shell练习题

你可能感兴趣的:(Linux,基础命令,Linux基础,test,bash,shell)