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语句语法如下:

case 值 in

模式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) "\nHello World !" >> test.txt

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

#输出到以日期格式文件名
echo -e $(date) "\nHello 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. $0Shell本身的文件名

posted @ 2022-11-10 19:26  彬在俊  阅读(243)  评论(0编辑  收藏  举报