• Linux脚本入门


    shell script

    P 450

    生成随机数

    #$RANDOM 会随机生成0到32767之间的数
    #一下生成0~30之间的数
    declare -i num=$RANDOM*30/36767;echo $num
    
    • 在编写script时经常需要用户输入信息,那么我们需要判断该变量是否赋值了,或者为空串,如何操作?
    filename=${fileuser:-"filename"} 
    #表示 如果变量filename不存在或为空白字符串,则将后面的值赋给filename变量。
    #其中 ilename=${fileuser-"filename"} 仅能给不存在的变量赋值
    #而加上 : 后则可以给不存在或为空白字符串赋值(类似于c语言中的默认参数,有则不变,无则用默认)
    

    创建最近三天的文件,文件名包含日期

    #!/bin/bash
    
    echo -e "该脚本将使用 'touch' 命令创建三个文件"
    read -p "请输入文件名称:" filename
    
    #判断文件名是否输入,若未输入则使用默认值
    filename=${filename:-"filename"}
    
    date1=$(date --date='2 days ago' +%Y%m%d) #两天前的日期
    date2=$(date --date='1 days ago' +%Y%m%d) #一天前的日期
    date3=$(date +%Y%m%d) #今天的日期
    
    file1=${filename}${date1}
    file2=${filename}${date2}
    file3=${filename}${date3}
    
    #创建文件
    touch "$file1"
    touch "$file2"
    touch "$file3"
    
    echo "创建成功,分别为:[$file1,$file2,$file3]"
    

    数值运算

    echo -e "You SHOULD input 2 numbers, I will cross them! 
    "
    read -p "first number: " firstnu
    read -p "second number: " secnu
    total=$(($firstnu*$secnu))
    echo -e "
    The result of $firstnu x $secnu is ==> $total"
    
    1. 这个档案是否存在,若不存在则给予一个『Filename does not exist』的讯息,并中断程序;
    2. 若这个档案存在,则判断他是个档案或目录,结果输出『Filename is regular file』或
      『Filename is directory』
    3. 判断一下,执行者的身份对这个档案或目录所拥有的权限,并输出权限数据!
    #!/bin/bash
    
    #判断文件是否存在
    echo "该脚本用于判断文件是否存在!"
    read -p "请输入要判断的文件名称:" filename
    
    #判断使用者是否输入了文件名
    test -z $filename && echo "您必须输入一个文件名!" && exit 0
    
    #判断文件是否存在
    test ! -e $filename && echo "名为 '$filename' 的文件不存在" && exit 0
    
    #判断文件类型
    test -f $filename && filetype="是文件"
    test -d $filename && filetype="是文件夹"
    test -r $filename && perm="$perm 可读"
    test -w $filename && perm="$perm 可写"
    test -x $filename && perm="$perm 可执行"
    
    #输出
    echo "文件 '$filename' 是 $filetype"
    echo "权限是:$perm"
    
    

    判断符号[]

    除了我们很喜欢使用的 test 之外,其实,我们还可以利用判断符号『 [ ] 』(就是中括号啦) 来进行数据的判断呢!

    如果我想要知道 $HOME 这个变量是否为空的,可以这样做:

    [root@www ~]# [ -z "$HOME" ] ; echo $?
    

    注意

    使用中括号必须要特别注意,因为中括号用在很多地方,包括通配符与正规表示法等等,所以如果要在
    bash 的语法当中使用中括号作为 shell 的判断式时,必须要注意中括号的两端需要有空格符来分隔
    喔! 假设我空格键使用『□』符号来表示,那么,在这些地方你都需要有空格键:

    [□"$HOME"□==□"$MAIL"□]
     ↑       ↑  ↑       ↑ 
    
    • 中括号使用规范
    • x 在中括号 [] 内的每个组件都需要有空格键来分隔;
    • x 在中括号内的变数,最好都以双引号括号起来;
    • x 在中括号内的常数,最好都以单或双引号括号起来。

    为什么要这么麻烦啊?直接举例来说,假如我设定了 name="VBird Tsai" ,然后这样判定:

    [root@www ~]# name="VBird Tsai"
    [root@www ~]# [ $name == "VBird" ]
    bash: [: too many arguments
    
    见鬼了!怎么会发生错误啊?bash 还跟我说错误是由于『太多参数 (arguments)』所致! 为什么呢?
    因为 $name 如果没有使用双引号刮起来,那么上面的判定式会变成:
    [ VBird Tsai == "VBird" ]
    上面肯定不对嘛!因为一个判断式仅能有两个数据的比对,上面 VBird 与 Tsai 还有 "VBird" 就有三个
    资料! 这不是我们要的!我们要的应该是底下这个样子:
    [ "VBird Tsai" == "VBird" ]
    

    1. 当执行一个程序的时候,这个程序会让用户选择 Y 或 N ,
    2. 如果用户输入 Y 或 y 时,就显示『 OK, continue 』
    3. 如果用户输入 n 或 N 时,就显示『 Oh, interrupt !』
    4. 如果不是 Y/y/N/n 之内的其他字符,就显示『 I don't know what your choice is 』
    #!/bin/bash
    
    read -p "请输入(y/n):" yn
    
    [ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK,continue" && exit 0
    
    [ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh,interupt!" && exit 0
    
    echo "I dot't know what you choice is" && exit 0
    

    脚本参数

    我们知道指令可以带有选项与参数,例如 ls -la 可以察看包含隐藏文件的所有属性与权限。那么 shell
    script 能不能在脚本档名后面带有参数呢?

    script 是怎么达成这个功能的呢?其实 script 针对参数已经有设定好一些变量名称了!对应如下:

    /path/to/scriptname opt1 opt2 opt3 opt4
          $0             $1   $2   $3   $4
    
    • $# :代表后接的参数『个数』,以上表为例这里显示为『 4 』;
    • $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
    • $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字符,默认为空格键, 所以本例中代表『 "$1
      $2 $3 $4" 』之意。

    • 程序的文件名为何?
    • 共有几个参数?
    • 若参数的个数小于 2 则告知使用者参数数量太少
    • 全部的参数内容为何?
    • 第一个参数为何?
    • 第二个参数为何
    #!/bin/bash
    
    echo "$0"
    echo "$#"
    [ "$#" -lt 2 ] && echo "参数太少" && exit 0
    echo "$@"
    echo "$1"
    echo "$2"
    

    条件判断式 (if...then)

    如果你只有一个判断式要进行,那么我们可以简单的这样看:
    if [ 条件判断式 ]; then
    当条件判断式成立时,可以进行的指令工作内容;
    fi <==将 if 反过来写,就成为 fi 啦!结束 if 之意!
    
    除了 sh06.sh 那个案例所写的,也就是『将多个条件写入一个中括号内的情况』之外, 我还可以有多
    个中括号来隔开喔!而括号与括号之间,则以 && 或 || 来隔开,他们的意义是:
    x && 代表 AND ;
    x || 代表 or ;
    所以,在使用中括号的判断式中, && 及 || 就与指令下达的状态不同了。举例来说, sh06.sh 里面的
    判断式可以这样修改:
    [ "$yn" == "Y" -o "$yn" == "y" ]
    上式可替换为
    [ "$yn" == "Y" ] || [ "$yn" == "y" ]
    

    多重、复杂条件判断式

    # 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况执行
    if [ 条件判断式一 ]; then
    当条件判断式一成立时,可以进行的指令工作内容;
    elif [ 条件判断式二 ]; then
    当条件判断式二成立时,可以进行的指令工作内容;
    fi
    

    如果考虑更复杂的情况,则可以使用这个语法:

    # 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况执行
    if [ 条件判断式一 ]; then
    当条件判断式一成立时,可以进行的指令工作内容;
    elif [ 条件判断式二 ]; then
    当条件判断式二成立时,可以进行的指令工作内容;
    else
    当条件判断式一与二均不成立时,可以进行的指令工作内容;
    fi
    
    #!/bin/bash
    
    read -p "请输入(y/n)" yn
    
    if [ "$yn"== "Y" ] || [ "$yn" == "y" ]; then
         echo "OK,continue"
    elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
         echo "On,interrupt!"
    else
         echo "I dot't know what your choice is"
    fi
    
    1. 判断 $1 是否为 hello,如果是的话,就显示 "Hello, how are you ?";
    2. 如果没有加任何参数,就提示使用者必须要使用的参数下达法;
    3. 而如果加入的参数不是 hello ,就提醒使用者仅能使用 hello 为参数。
    #!/bin/bash
    
    if [ "$1" == "hello" ]; then
        echo "hello"
    elif [ "$1" == "" ]; then
        echo "you MUST input param ex> {$0 someword}"
    else
       echo "the only param is 'hello'> {$0 hello}"
    fi
    
    

    检测 80 ,21,22,25端口是否占用

    #!/bin/bash
    
    echo "开始检测 www(80),ftp(21),ssh(22),mail(25) 端口是否占用!"
    
    testing=$(netstat -tuln | grep ":80") #查看80端口是否被占用
    
    if [ "$testing" != "" ]; then
       echo "www(80) 端口正在使用"
    else
       echo "www(80) 端口未被占用"
    fi
    
    
    testing=$(netstat -tuln | grep ":22") #查看80端口是否被占用
    
    if [ "$testing" != "" ]; then
       echo "ssh(22) 端口正在使用"
    
    else
       echo "ssh(22) 端口未被占用"
    fi
    
    
    testing=$(netstat -tuln | grep ":21") #查看80端口是否被占用
    if [ "$testing" != "" ]; then
       echo "ftp(21) 端口正在使用"
    
    else
       echo "ftp(21) 端口未被占用"
    fi
    
    
    testing=$(netstat -tuln | grep ":25") #查看80端口是否被占用
    if [ "$testing" != "" ]; then
       echo "mail(25) 端口正在使用"
    
    else
       echo "mail(25) 端口未被占用"
    fi
    

    case ..... esac

    #!/bin/bash
    # 判断第一个参数
    case $1 in
            "start")
                    echo "正在启动中..."
            ;;
            "stop")
                    echo "停止中..."
            ;;
            *)
                    echo "参数错误,请输入 start or stop"
            ;;
    esac
    

    function 函数

    #!/bin/bash
    
    function printit(){
            echo "你传入的参数是$1,$2" # 这里$1是调用函数传入的参数
    }
    
    case $1 in
            "one")
                    printit 1 3 #这里传入的参数是1
            ;;
            "two")
                    printit 2 3
            ;;
            "three")
                    printit 3 3
            ;;
            *)
                    echo "请输入 one | two | three"
            ;;
    esac
    

    test

    [root@10-9-69-125 scripts]# sh function.sh one
    你传入的参数是1,3
    
    [root@10-9-69-125 scripts]# sh function.sh three
    你传入的参数是3,3
    
    [root@10-9-69-125 scripts]# sh function.sh aaa
    请输入 one | two | three
    

    循环(loop)

    while do done, until do done (不定循环)

    • while do done
    while [ condition ]  <==中括号内的状态就是判断式 
    do            <==do 是循环的开始!  
        程序段落 
    done          <==done 是循环的结束 
    

    说明

    当 condition 条件成立时,就进行循环,直到 condition 的条件不成立才停止

    • until do done
    until [ condition ] 
    do  
        程序段落 
    done
    

    说明

    这种方式恰恰与 while 相反,它说的是『当 condition 条件成立时,就终止循环, 否则就持续进行循 环的程序段。』是否刚好相反啊~

    示例:

    从1累加到100

    #!/bin/bash
    
    #从1累加到100
    
    sum=0 #计数总和
    i=0 #累计值
    
    while [ "$i" != "100" ]
    do
            i=$(($i+1)) #i加1
            s=$(($s+$i)) #累加
    done
    
    echo "1...100总和为:=>$s"
    

    for...do...done (固定循环)

    for var in con1 con2 con3 ... 
    do  
        程序段 
    done 
    
    以上面的例子来说,这个 $var 的变量内容在循环工作时: 
    1. 第一次循环时, $var 的内容为 con1 ; 
    2. 第二次循环时, $var 的内容为 con2 ; 
    3. 第三次循环时, $var 的内容为 con3 ; 
    4. .... 
    

    示例

    1、 获取系统用户名

    #!/bin/bash
    
    users=$(cut -d ':' -f1 /etc/passwd) # 获取账号
    for username in $users
    do
            echo "username: $username"
    done
    
    

    2、ping 局域网内192.168.1.1 ~ 192.168.1.100 的网络是否连通

    #!/bin/bash
    
    network="192.168.1" #定义前面部分
    
    for sitenu in $(seq 100 130) #seq 为 sequence(连续) 的缩写
    do
            #判断是否ping通
            ping -c 1 -w 1 ${network}.${sitenu} &> /dev/null && result=0 || result=1
            #显示结果
            if [ "$result" == 0 ];then
                    echo "ip ${network}.${sitenu} Ok"
            else
                    echo "ip ${network}.${sitenu} Error"
            fi
    
    done
    
    

    for 的第二种写法

    for (( 初始值; 限制值; 执行步阶 )) 
    do  
        程序段 
    done
    

    示例

    计算从1到用户输入值的和

    #!/bin/bash
    
    #计算从1到你指定的数的和
    
    read -p "计算从1到您指定的数的和,请输入:" nu
    
    s=0
    for ((i=1;i<=$nu;i=i+1))
    do
            s=$(($s+$i))
    done
    
    echo "从1计算到$nu的和为:$s"
    

    shell debug

     sh [-nvx] scripts.sh 
     -n  :不要执行 script,仅查询语法的问题;
     -v  :再执行 sccript 前,先将 scripts 的内容输出到屏幕上; 
     -x  :将使用到的 script 内容显示到屏幕上,这是很有用的参数! 
    
    范例一:测试 sh16.sh 有无语法的问题?
    [root@www ~]# sh -n sh16.sh  
    # 若语法没有问题,则不会显示任何信息! 
     
    范例二:将 sh15.sh 的执行过程全部列出来~
    [root@www ~]# sh -x sh15.sh  
    + PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/bin 
    + export PATH 
    + for animal in dog cat elephant 
    + echo 'There are dogs.... ' There are dogs.... 
    + for animal in dog cat elephant + echo 'There are cats.... ' There are cats.... 
    + for animal in dog cat elephant 
    + echo 'There are elephants.... ' 
    There are elephants.... 
    

    合并以.txt结尾的文件到新文件中

    #!/bin/bash
    
    dirs=`ls /home/mgy/data|grep '.txt$'` # 查找.txt结尾的文件
    newfile=`touch mar.txt`   # 创建新文件
    
    for file in $dirs    # 循环文件列表
    do
            `cat $file >> mar.txt`   # 依次将.txt结尾文件内容写入mar.txt
    done
    
  • 相关阅读:
    where T: class的解释
    调用钉钉的WebAPI接口实现与ERP数据的同步
    Json序列化和反序列化的方式
    Log4Net日志处理
    MVC项目中异常处理
    FindBI商业智能报表工具
    权限列表实现
    委托,匿名,lambda
    [经典贪心算法]贪心算法概述
    [zt]手把手教你写对拍程序(PASCAL)
  • 原文地址:https://www.cnblogs.com/maguangyi/p/14215228.html
Copyright © 2020-2023  润新知