zoukankan      html  css  js  c++  java
  • shell脚本

    前言

    今天开始shell的学习,shell是核心程序Kernel之外的命令解析器,是一个程序,也是一种命令语言和程序设计语言。作为一种命令语言,可以交互式解析用户输入的命令。

    比如输入ls命令后,shell会解析ls这个字符并向内核发出请求,内核执行这个命令之后把结果告诉shell,shell会把结果输出到屏幕。linux 默认的shell是bash。

    shell脚本基本元素

    获取shell 脚本名 echo $0

    或者 echo bashname

    获取文件夹路径 dirname $0 

     

    shell 变量

    定义一个变量

    your_name="runoob.com"
    • =左右不能加空格
    • 变量名不加$
    • 不能有标点符号
    • 不能使用保留关键字符(可直接输入help 查看保留关键字)

    使用变量

    使用一个定义过的变量,只要在变量名前面加美元符号即可,如:

    your_name="qinjx"
    echo $your_name
    echo ${your_name}

    变量名外的花括号是可选的,主要是为了界定变量的边界

    your_name="qinjx"
    echo $your_nameis my friend
    echo ${your_name}is my friend

    他会认为your_nameis 是个变量(其值为空)

    编程习惯是:对变量名都加上花括号


     

    shell 内部变量

    • PWD 当前的工作目录
    • RANDOM 每次引用这个变量时都会生成一个均匀分布的0~32767 范围内的随机整数
    • SCONDS 脚本已经运行的时间
    • PPID 当前进程的父进程的进程ID
    • $? 表示最近一次执行命令或shell 脚本的出口状态

    shell 环境变量

    主要环境变量如下:

    • EDITOR 
    • HOME 用户主目录
    • PATH 指定命令的检索路径

    shell字符串

    最好用双引号来引用字符串

    双引号的优点:

    • 双引号里可以有变量
    • 双引号里可以出现转义字符

    拼接字符串

    your_name="runoob"
    # 使用双引号拼接
    greeting="hello, "$your_name" !"
    greeting_1="hello, ${your_name} !"
    echo $greeting  $greeting_1
    # 使用单引号拼接
    greeting_2='hello, '$your_name' !'
    greeting_3='hello, ${your_name} !'
    echo $greeting_2  $greeting_3

    输出结果为:

    hello, runoob ! hello, runoob !
    hello, runoob ! hello, ${your_name} !

    获取字符串长度

    string="abcd"
    echo ${#string} #输出 4

    提取子字符串

    以下实例从字符串第 2 个字符开始截取 4 个字符:

    string="runoob is a great site"
    echo ${string:1:4} # 输出 unoo

    注意:第一个字符的索引值为 0

     

    查找子字符串

    查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):

    string="runoob is a great site"
    echo `expr index "$string" io`  # 输出 4

    注意: 以上脚本中 ` 是反引号,而不是单引号 ',不要看错了哦。


    Shell 数组

    定义数组

    在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:

    数组名=(值1 值2 ... 值n)

    例如:

    array_name=(value0 value1 value2 value3)

    或者

    array_name=(
    value0
    value1
    value2
    value3
    )

    还可以:

    array_name[0]=value0
    array_name[1]=value1
    array_name[n]=valuen

    读取数组

    读取数组元素值的一般格式是:

    ${数组名[下标]}

    例如:

    valuen=${array_name[n]}

     

    使用 @ 符号可以获取数组中的所有元素,例如:

    echo ${array_name[@]}

    获取数组的长度

    获取数组长度的方法与获取字符串长度的方法相同,例如:

    # 取得数组元素的个数
    length=${#array_name[@]}
    # 或者
    length=${#array_name[*]}
    # 取得数组单个元素的长度
    lengthn=${#array_name[n]}

    Shell 注释

    单行注释

    以 # 开头的行就是注释,会被解释器忽略。

    多行注释

    多行注释还可以使用以下格式:

    :<<EOF
    注释内容...
    注释内容...
    注释内容...
    EOF

    Shell 传递参数

    我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$nn 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……

    实例

    以下实例我们向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径):

    #!/bin/bash
    # author:菜鸟教程
    # url:www.runoob.com
    
    echo "Shell 传递参数实例!";
    echo "执行的文件名:$0";
    echo "第一个参数为:$1";
    echo "第二个参数为:$2";
    echo "第三个参数为:$3";

    shell中的控制流结构

    if

     if语句语法如下:

    if
    then
        命令1
    else
        命令2
    fi

    案例如下:

    if [[ ${num} < 10 ]]
    then
            echo "输入数字小于10"
    else
            echo "输入数字大于10"
    fi

    if语句语法进阶用法:

    if 条件1
    then
           命令1
    elif    条件2
    then
           命令2
    else
           命令3
    fi

    案例如下:

    num=$1
    
    if [[ ${num} -lt 100 ]] && [[ ${num} -ge 90 ]]
    then
            echo ""
    elif [[ ${num} -lt 90 ]] && [[ ${num} -ge 80 ]]
    then
            echo ""
    else
            echo ""
    fi

    case:

    case语句语法如下:

    casein
    
    模式1)
    
      命令1
    
      ;;
    
    模式2)
    
      命令2
    
      ;;
    
    *)
    
      命令3
    
      ;;
    
    esac

    案例如下:

    #!/bin/bash
    #case select
    echo -n "Enter a num form 1 to 3:"
    read ANS
    case $ANS in
    
    1)
            echo "you select 1 ..."
            ;;
    
    2)
            echo "you select 2 ..."
            ;;
    
    3)
            echo "you select 3 ..."
            ;;
    *)
            echo "`basename $0` : this is not between 1 and 3"
            exit;
            ;;
    esac

    for语法:

    for 变量名 in 列表
    do
        命令
    done

    案例如下:

    #!/bin/bash
    
    for n in {100..200}
    do
            host=192.168.1.$n
            ping -c2 $host &>/dev/null
            if [ $? = 0 ];then
                    echo "$host is UP"
            else
                    echo "$host is DONE"
            fi
    done

    使用shell脚本遍历日期

    date=$(date +%Y-%m-%d)
    for (( i=0; i < 30; i++ )) 
    do
        date=$(date -d "${date} -1 days" +%Y-%m-%d)
        echo "curl 32.61.51.61/$date"
    done

    1. 按天倒序遍历日期 ( 正序修改一下日期增减函数即可 )

    #!/bin/bash
     
    #倒序按天遍历日期
     
    #传入遍历的开始时间和结束时间
    startdate="$1"
    enddate="$2"
     
    echo 'startdate: '$startdate
    echo 'enddate: '$enddate
    echo "-----------------------------------"
     
    #序列1-300,表示遍历300次,因为有结束时间的限制,所以实际上不会循环300次
    for i in `seq 1 300`; do 
      #当开始时间小于结束时间时,直接结束脚本
      if [[ $startdate -lt $enddate ]]; then
        break
      fi
      echo $startdate 
      #执行hiveSQL脚本,我是需要按日期执行hiveSQL,这里可以无视
      hive -hiveconf input_date=$startdate -f mergeSmallFiles.sql # >> mergeSmallFiles.txt
      #每次执行后,使开始日期减一天,如果要正序,将下面-1换成+1即可,当然开始时间和结束时间也要换一下
      startdate=$(date -d "$startdate -1 day" +%Y%m%d)
    done

    #!/bin/bash
    #文件名:test.sh
    name="xiongzaiqiren"
    echo $name
    
    echo "BACKUP DATE:" $(date +"%Y-%m-%d %H:%M:%S")
    
    DATE=`date '+%Y%m%d-%H%M%S'`
    echo $DATE
    
    LogNameDATE=`date '+%Y%m%d'`
    
    echo " " >> log$LogNameDATE.log
    echo "———————————————–" >> log$LogNameDATE.log
    echo "BACKUP DATE:" $(date +"%Y-%m-%d %H:%M:%S") >> log$LogNameDATE.log
    echo "———————————————– " >> log$LogNameDATE.log

    当前日期格式输出:

    #将当前时间和包含换行符的文本内容输出到文件
    echo -e $(date) "
    Hello World !" >> test.txt
    
    #将当前时间(格式化)和包含换行符的文本内容输出到文件
    echo -e `date '+%Y-%m-%d %H:%M:%S %A'` "
    Hello World !" >> test.txt
    #同上,简化版。
    echo -e `date '+%F %T %A'` "
    Hello World !" >> test.txt
    
    #输出到以日期格式文件名
    echo -e $(date) "
    Hello World !" >> test`date +'%Y-%m-%d'`.txt

    ORACLE_TABLE=(`cat /root/ORACLE_TABLE.txt | awk '{print $1}'`)
    HDFS_PATH=(`cat /root/ORACLE_TABLE.txt | awk '{print tolower($1)}'`)
    TABLE_COUNTS=(`cat /root/ORACLE_TABLE.txt | wc -l`)
    
    for(( i=0; i < $TABLE_COUNTS; i++ ))
    do
        echo tablename: ${ORACLE_TABLE[$i]} ------ HDFS_PATH: ${HDFS_PATH[$i]}
    done

    获取数组的长度

    ${#my_array[*]}

    shell远程执行:

    ssh user@node1 "cd /home ; ls" 
    例: ssh root
    @node1 "sh /root/sqoop-hdfs.sh"

    总结:

      (1)$(cmd)与··(键盘上1左边的~)一样,都是命令替换,可以将执行结果提取出来

      (2)[]使用的时候[  ]前后都必须有空格,且两个字符或数字之间的比较符左右也必须有空格。

      (3)   []是test的另一种形式,[]中间只能使用= 和 != 比较字符串,如果使用< 、>需要进行转义。

        []中间如果比较数字需要用 -lt 等符号,不能使用<比较数字,会当成字符串处理。

      (4)[[]]可用于处理逻辑命令,也可以用于处理字符串是否相等,且使用<、>不用转义符.

      (5)(())可用于比较数字,且不用转义,而且也可以用于数字计算,比较的时候也是用普通的>,<。(())计算的时候运算符与数字之间不能有空格,例如: sum=$(($sum+4))

      (6)字符串比较 用[],与普通的<,>,=,!=符号,如果使用<,>需要转义;或者使用[[]]比较字符串也是用普通符号不用转义

        数字比较用[]的时候用-lt,-gt等符号,不能使用<(因为会当成字符串处理);或者用(())比较数字用普通符号不用转义

      (7)可以将$理解为取变量的符号,$var 或者 ${}  ,在不影响语义的情况下可以省去{},但是最好写上{}。例如:test=XXX.$testWWWW.这时候就必须加上{}变为${test}WWWW

    shell脚本中的$0, $?, $!, $$, $*, $#, #@的

    1. $$
    Shell本身的PID(ProcessID)


    2. $!
    Shell最后运行的后台Process的PID


    3. $?
    最后运行的命令的结束代码(返回值)


    4. $-
    使用Set命令设定的Flag一览


    5. $*

    如果加" ",即"$*"则表示视所有该命令参数为一个单词,如果没有" ",那么该命令每一个参数

    都视为独立的参数。比如传入的参数:1 2 3 4,$*:表示1 2 3 4;"$*":表示1,2,3,4

     


    6. $@
    不管有" "没有" ",每个参数都是独立的,但是,如果传入的参数比如是:1 "2 3" 4,那就有点差异了,"$@": 表示1,2  3,4;而$@:表示1,2,3,4


    7. $#
    添加到Shell的参数个数


    8. $0
    Shell本身的文件名

    shell中 -eq,-ne,-gt,-lt,-ge,-le数字比较符

    -eq //equals等于
    -ne //no equals不等于
    -gt //greater than 大于
    -lt //less than小于
    -ge //greater equals大于等于
    -le //less equals小于等于

    注:

    1、在shell中进行比较时,结果为0代表真,为1代表假。

    2、-eq,-ne等比较符只能用于数字比较,有字符也会先转换成数字然后进行比较。

  • 相关阅读:
    Error Code: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use...
    php-fpm.conf
    php扩展模块redis安装
    php中configure报错问题
    Linux基础之重定向|grep
    Linux基础之基本命令cat less more sort uniq alias 命令行 bash简单描述(三)
    生产环境下正则的应用实例(一)
    mysql5.7.20主从和主主搭建
    Linux基础之vi编辑器(二)
    svn
  • 原文地址:https://www.cnblogs.com/erlou96/p/14137428.html
Copyright © 2011-2022 走看看