一、自定义变量

declare 声明 shell 变量,若不加上任何参数,则会显示全部的shell变量与函数(与执行set指令的效果相同)。 

   -a  :将后面名为variable 的变量定义成为数组 (array) 类型  

   -i  :将后面名为variable 的变量定义成为整数数字 (integer) 类型  

   -x  :用法不 export 一样,就是将后面的 variable 变成环境变量

   -r  :将变量设定成为readonly 类型,该变量不可被更改内容,也不能unset 

   -f  :显示函数的内容(不带函数名,就是显示所有函数)

         declare -f function_name


二、位置变量

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

位置变量   $1  $2 .....    ${10}

$1 $2是取shell脚本后的变量

$0是取shell脚本的名字本身

$*是取一个脚本的所有位置变量

$@也是取一个脚本的所有位置变量,区别在于$*取出的多个值是多个字符串,$@取出的值是一个字符串

$#表示所有位置变量的个数

$$表示当前进程的ID号


三、变量的展开和替换

Syntax

description
${var:-value}

如果变量var没有被定义或为空,就使用默认值value来代替变量var的值,但是不会改变var的值

wKioL1VQTqnSJfh0AAB_e71EN0E997.jpg

${var:+value}

如果变量var不为空,就使用默认值value来代替变量var的值,但是不会改变var的值;如果变量var为空,不进行任何替换返回null

wKioL1VQTsriPtg-AACRhoZTDPY432.jpg

${var:=value}

如果变量var没有被定义或为空,在返回value的值的同时把值value赋给它

wKiom1VQTXTilcNtAACXvUjDX3k992.jpg

${var:?msg}

若变量已赋值的话,返回var的值;如果变量var的值为空,那么打印msg到标准错误输出并退出脚本

wKiom1VQTYCjHHKNAAC4lyu2Pp4886.jpg

${#value}         变量的字符个数(变量的字符个数,并不是变量的个数)

wKiom1VQYw-iVwj6AABfavFb5J4040.jpg

${value:offset}和${value:offset:length}

从变量中提取子串,这里offset和length可以是算术表达式

Shell脚本实例_第1张图片

${value#pattern}和${value##pattern}           去掉value中与pattern相匹配的部分(pattern可以写linux通配符,如*?)

${value##pattern}

对$value的变量按pattern模式进行匹配(从左向右),将匹配到的最长一个匹配值及其左边的值去掉后返回。又叫最长模式。

${value#pattern}
对$value的变量按pattern模式进行匹配(从左向右),并将匹配到的最短的一个及其左边的值去掉后返回。又叫最短模式。

Shell脚本实例_第2张图片 

${value%pattern}和${value%%pattern}

和上面的一样,只是是从value的尾部与pattern相匹配,%与%%的区别与#与##一样

wKioL1VQT8KyeR3KAACFy5TQC44262.jpg

${value/pattern/string}和${value//pattern/string}

进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/只替换第一个匹配字符,//是全部替换

wKioL1VQT9DTSX6wAACpuC7ICs8555.jpg


四、数组

声明一个数组:

declare -a Name

 

赋值方法1:

Name[0]="zhu"

Name[1]="wang"

Name[2]="ding"

Name[6]="sun"   #可以这样赋值,这样赋值就会有7个元素,其中3、4、5的值为空

赋值方法2:

Name=("zhu ssui" wang ding sun)  #每个元素之间用空格分开,这样赋值就只有4个元素

Name=([0]="zhu"[1]="wang" [2]="ding" [6]="sun")    #同赋值方法1

 

对数组元素的引用:

${Name[index]}

${Name[*]}和${Name[@]}    显示数组中所有元素

 

某个元素中字符的个数(长度):

${#Name[index]}

${#Name} = ${#Name[0]}

 

整个数组中非空的元素的个数:

${#Name[*]}  或者   ${#Name[@]}

 

五、带颜色输出的shell 

-e 用来开启echo中的转义

\e 或 \033 来输出Esc符号

设置颜色的格式: \e[背景色;前景色;高亮m

                  \033[背景色;前景色;高亮m

恢复默认为\e[0m或\033[0m

第一个参数

其中背景色可以被以下数字替换

0 透明(使用终端颜色),1 高亮 40 黑,41 红, 42 绿, 43 黄, 44 蓝 45 紫, 46 青绿, 47白(灰)

第二个参数:

前景色(也就是字体的颜色)可以被以下数字替换

30 黑 31 红, 32 绿, 33 黄, 34蓝, 35 紫, 36 青绿, 37 白(灰)

第三个参数

高亮是1,不高亮是0

第四个参数为m:

注意m后面紧跟字符串

参数不一定要写全,可以部分省略的

Shell脚本实例_第3张图片

 

六、脚本实例

这个脚本主要是用来分发配置文件到各个平台服务上的。它自己会读2个配置文件list-user和list-user2。

[root@localhost distribution]# cat list-user
192.168.1.22       1377
192.158.1.23       178   #就是这种格式,IP地址对应平台名字


#!/bin/bash
#
my_fun1()
{
    for HOST in `cat list-user | grep $1 | awk '{print $1}'`; do
        echo "====================================$1====================================="
        scp /media/Slamdunk/Resources_Test/$1/Server/cfg/IniFile/* user@$HOST:~/release/cfg/IniFile/
    done
}
#分发函数
my_fun2()
{
    for HOST in `cat list-user2 | grep $1 | awk '{print $1}'`; do
        echo "====================================$1====================================="
        scp /media/Slamdunk/Resources_Test/$1/Server/cfg/IniFile/* user2@$HOST:~/release/cfg/IniFile/
    done
}
declare -a menus        #声明一个菜单数组
declare -i index=1      #声明数组索引的起始值
#检测配置文件的平台是否存在
for I in `cat list-user* | awk '{print $2}' | uniq -c | awk '{print $2}'`; do
    ls /media/Slamdunk/Resources_Test/ | grep $I > /dev/null
    if [ $? -ne 0 ]; then
        echo "Wrong Config File!!!"
        echo "$I platform not exist!!!"
        exit 1
    else
        menus[index]=$I              #将平台名字填入数组中
       index=$[$index+1]
    fi
done
#显示菜单
echo -en "\e[33;1m"                   #开启***字体
for ((i=1;i<=$index;i++)); do
    if [ $(($i%6)) -eq 0 ]; then      #每行显示6个
        printf "%d)%-15s\t" $i ${menus[i]}                  #设置字符串的长度为15,加上Tab键可以完成列的对齐
        echo 
    else
        printf "%d)%-15s\t" $i ${menus[i]}
    fi
done
echo -e "\e[0m"                       #关闭颜色显示
 
read -p "please input platform name: " PLAT
#所有平台都分发
if [ $PLAT = 'all' ];then
    for FILE in 'list-user' 'list-user2'; do
        for F_PLAT in `cat $FILE | awk '{print $2}' | uniq -c | awk '{print $2}'`; do
            if [ $FILE = 'list-user' ]; then
                my_fun1 $F_PLAT
            else 
                my_fun2 $F_PLAT
            fi
        done
    done
    exit 0
fi
#按输入的平台进行分发
cat list-user | grep $PLAT > /dev/null
if [ $? -eq 0 ]; then
    my_fun1 $PLAT 
else
    cat list-user2 | grep $PLAT > /dev/null
    if [ $? -eq 0 ]; then
        my_fun2 $PLAT
    else 
        echo "Please Input Corrent Platform Name. Thank You."
        exit 1
    fi
fi

脚本中,检查配置文件那边用到了数组,显示菜单那边用到了格式化输出和颜色输出。执行效果如下:

wKiom1VQV9uz8pHRAAItFVw6rfY137.jpg

 

下面这个脚本是用用来解密配置文件(用到了变量的展开):

for I in `diff /tmp/RecordDBCfg.xml /tmp/RecordDBCfg.xml.bak | awk -F ['>''"''<'] '{if ($8 ~ /^lmOf/) print $4"-"$8; else print "=";}'`; do 
	if [ $I = '=' ]; then 
		echo "================="
	else 
		echo ${I%-*} `~/tools/dbdecode ${I#*-}`
	fi
done

现在先进行步骤分解,首先看看diff里面的输出:

wKiom1VQWf3Bf4vbAAS7bb7YFIs432.jpg

再看awk后的输出:

wKioL1VQXBWQEtTrAAQDI2T-kHA903.jpg

awk的主要作用就是将id和密文取出来,接下来就是变量的展开了。

${I%-*}  就是去掉$I中“-”后面的部分,只留下id

${I#*-}  就是去掉$I中“-”前面的部分,只留下密文,然后进行解密