shell编程企业级实战(2)

Vim配置文件.vimrc

vim配置文件

if 条件语句

if是最常见的条件判断语句

例1:如果不存在/backup目录就创建。
[root@web-01 /server/tools]# vim 07-01.sh#!/bin/baspath=/backup[ -d $path ] || mkdir $path -p# 相当于# :冒号表示什么也不干if [ -d $path ] then        :else        mkdir $path -pfi# 或者[ !-d $path ] && mkdir /backdir -p# 相当于if [ !-d $path ] then        mkdir /backdir -pif"07-01.sh" 18L, 248C writtevim命令:替换:%s#/backup#$path#g
例2:开发Shell脚本判断系统剩余内存的大小,如果低于100MB就提示内存不足,否则提示内存充足。
考查if双分支:
分析:
1)提取系统内存。
2)if判断,
[root@web01 07]# cat 07_02.sh
#!/bin/bash
##############################################################
# File Name: 07_02.sh
# Version: V1.0
# Author: pizza
# Created Time : 2018-06-06 22:58:54
# Description:
##############################################################
mem=`free -m|awk ‘NR==3{print $NF}‘`
if [ $mem -lt 1000 ]
then
    echo "内存严重不足。"
else
    echo "内存还够"
fi

在第一章的中添加了内存不足发邮件的例子
例3:分别使用变量定义、read读入及脚本传参方式实现比较2个整数的大小。
1)变量定义:
a=6
b=2
2)read读入:
read -p "请输入两个数字:" a b
3)传参:
分析:
大于 等于 小于
#!/bin/bash############################################################### File Name: 07-03.sh# Version: V1.0# Author: pizza# Created Time : 2019-03-28 21:20:46# Description:############################################################### 第一种,传参a=6b=7# 第二种,readread -p "请输入两个数字" a b# 第三种,参数$a=$1$b=$2# 判断输入# 1、判断数字是不是够,判断b是不是空,或者使用$## 2、判断是不是整数,利用expr# 3、

if [ $a -gt $b ]then    echo "$a>$b"elif [ $a -lt $b ]then    echo "$a<$b"else    echo "$a=$b"fi

例4:打印一个菜单如下,当用户选择对应的数字时,就执行对应项的应用。
  1.install lamp
  2.install lnmp
  3.exit

第一章已讲解:
bash内置核心命令read的企业级应用实践
read企业应用
[root@web01 scripts]# cat select1.sh
#!/bin/bash
cat <<EOF
  1.install lamp
  2.install lnmp
  3.exit
EOF
read -p "请选择一个序号(必须是数字):" num
#1.判断是否为整数
expr 2 + $num &>/dev/null
if [ $? -ne 0 ]
then
    echo "Usage:$0 {1|2|3}"
    exit 1
fi

#2.判断执行处理
if [ $num -eq 1 ]
then
    echo "install lamp..."
elif [ $num -eq 2 ]
then
    echo "install lnmp..."
elif [ $num -eq 3 ]
then
    echo "bye."
    exit
else
    echo "Usage:$0 {1|2|3}"
    exit 1
fi

Shell函数的知识与实践

函数的作用就是将程序里多次被调用的相同代码组合起来,并为其取个名字。其他所有想重复调用这部分代码的复方都只需要调用这个这个名字就可以了。当需要修稿这部分重复代码的时候,也只需要改变函数内的一份代码即可实现所有的修改,也可以把函数独立写到文件里面,当需要调用的时候,再加载进来。

函数的语法体

oldboy() {
    echo "I am oldboy."
}
function oldgirl {
    echo "I am oldgirl."
}
test() {
    echo "Hello world."
}
oldboy
oldgirl

[root@web-01 ~]# sh test_hanshu.shI am oldboy.I am oldgirl.Hello world.[root@web-01 ~]# 

向函数传参

带参数的函数编写执行
oldboy() {
    echo "I am $1."
}
oldboy oldboy
将函数传参转为脚本传参
oldboy() {
    echo "I am $1."
}
oldboy $1

函数和执行函数分离./etc/init.d/functionpizza $1

Shell函数的执行注意事项

企业案例:通过脚本传参的方式,检查Web 网站URL是否正常。

wget命令:
--spider 模拟爬虫
-q 安静访问
-o /dev/null 不输出
-T --timeout 超时时间
-t --tries 重试次数
[root@web01 ~]# wget --spider -T 5 -q -o /dev/null -t 2 www.baidu.com
[root@web01 ~]# echo $?
0
curl命令:
-I 看响应头
-s 安静的 安静模式。不显示进度表或错误信息。使cURL 不反馈信息。
-o /dev/null 不输出
-w %{http_code} 返回状态码,200-m 超时时间
[root@web01 ~]# curl www.baidu.com -s &>/dev/null
[root@web01 ~]# echo $?
0
[root@web01 ~]# curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null  www.baidu.com
200

不用函数的实现写法
#!/bin/sh
if [ $# -ne 1 ]
  then
    echo $"usage:$0 url"
    exit 1
fi
wget --spider -q -o /dev/null --tries=1 -T 5 $1 #<==-T指定超时时间,这里的$1为脚本的参数。
if [ $? -eq 0 ]
then
    echo "$1 is yes."
else
    echo "$1 is no."
fi
高端专业的函数写法:

[root@oldboy ~]# cat checkurl.sh
#!/bin/bash
##############################################################
# File Name: checkurl.sh
# Version: V1.0
# Author: oldboy
# Organization: www.oldboyedu.com
# Created Time : 2018-06-07 18:29:19
# Description:
##############################################################
usage(){
    echo "Usage:$0 url"
    exit 1
}
checkurl(){
    wget -q -o /dev/null -t 2 -T 5 $1
    if [ $? -eq 0 ]
    then
        echo "$1 is ok"
    else
        echo "$1 is fail"
    fi
}
main(){
    if [ $# -ne 1 ]
    then
        usage
    fi
    checkurl $1
}
main $*

[root@oldboy scripts]# cat 8_5_1.sh
#!/bin/sh
function usage() {     #<==帮助函数
    echo $"usage:$0 url"
    exit 1
}

function check_url() { #<==检测URL函数。
  wget --spider -q -o /dev/null --tries=1 -T 5 $1 #<==这里的$1就是函数传参。
  if [ $? -eq 0 ]
   then
     echo "$1 is yes."
  else
    echo "$1 is no."
  fi
}

function main() {   #<==主函数。
  if [ $# -ne 1 ]   #<==如果传入的多个参数,则打印帮助函数,提示用户。
  then
    usage
  fi
  check_url $1     #<==接收函数的传参,即把结尾的$*传到这里。
}
main $*            #<==这里的$*就是把命令行接收的所有参数作为函数参数传给函数内部,常用手法。

CASE结构条件句

几乎所有的case都可以用if替代
case "$1" in
    1)
    dddd
    ;;
    2)
    dddd
    ;;
    *)
    dddd
esac

企业应用:
启动脚本
read 读入 菜单选择。

范例9_2:执行shell脚本,打印一个如下的水果菜单:
1.apple
2.pear
3.banana
4.cherry
当用户输入对应的数字选择水果的时候,告诉他选择的水果是什么,并给水果单词加上一种颜色(随意),要求用case语句实现。
范例9_3:给内容加不同的颜色。
内容的颜色用数字表示,范围为30-37,每个数字代表一种颜色。代码如下:
echo -e "\033[30m 黑色字 \033[0m" #<==30m表示黑色字。
echo -e "\033[31m 红色字 \033[0m" #<==31m表示红色字。
echo -e "\033[32m 绿色字 \033[0m" #<==32m表示绿色字。
echo -e "\033[33m 棕色字 \033[0m" #<==33m表示棕色字(brown),和黄色字相近。
echo -e "\033[34m 蓝色字 \033[0m" #<==34m表示蓝色字。
echo -e "\033[35m 洋红字 \033[0m" #<==35m表示洋红色字(magenta),和紫色字相近。
echo -e "\033[36m 蓝绿色 \033[0m" #<==36m表示蓝绿色字(cyan),和浅蓝色字相近。
echo -e "\033[37m 白色字 \033[0m" #<==37m表示白色字。
说明:不同的数字对应的字体颜色,见系统帮助(来源man console_codes命令的结果)。
范例9_6: 给输出的字符串加不同的背景颜色。
字的背景颜色对应的数字范围为40-47,代码如下。
echo -e "\033[40;37m 黑底白字\033[0m"   #<==40m表示黑色背景。
echo -e "\033[41;37m 红底白字\033[0m"   #<==41m表示红色背景。
echo -e "\033[42;37m 绿底白字\033[0m"   #<==42m表示绿色背景。
echo -e "\033[43;37m 棕底白字\033[0m"   #<==43m表示棕色背景(brown),和黄色背景相近。
echo -e "\033[44;37m 蓝底白字\033[0m"   #<==44m表示蓝色背景。
echo -e "\033[45;37m 洋红底白字\033[0m"  #<==45m表示洋红色背景(magenta),和紫色背景相近。
echo -e "\033[46;37m 蓝绿底白字\033[0m"   #<==46m表示蓝绿色背景(cyan),和浅蓝色背景相近。
echo -e "\033[47;30m 白底黑字\033[0m"    #<==47m表示白色背景。
创建case3.sh,定义函数 ,执行函数color $*创建case4.sh,用.或者source调用函数,打印菜单,输入数字,显示不同颜色的字体
范例9_10:利用case语句开发Rsync服务启动停止脚本,本例采用case语句以及新的思路来实现。
分析:
启动:
rsync --daemon
停止:
pkill rsync
killall rsync
kill 进程号    ---->最专业的方法
/etc/init.d/rsyncd {start|stop|restart}
case

rsync.sh简单版

case "$1" in
    start)
        rsync --deamon
        if [ $? -eq 0 ]
        then
            echo "rsync startup ok"
        else
            echo "rsync startup fail"
        fi
        ;;
    stop)
        killall rsync
        if [ $? -eq 0 ]
        then
            echo "rsync stop ok"
        else
            echo "rsync stop fail"
        fi
        ;;
    restart)
        killall rsync && sleep 1 && rsync --deamon
        if [ $? -eq 0 ]
        then
            echo "rsync restart ok"
        else
            echo "rsync restart fail"
        fi
        ;;

    *)
        echo "usage:$0 {start|stop|restart}"
        exit 1
esac

升级版

 start(){
     rsync --deamon
     retval=$?
     if [ $retval -eq 0 ]
     then
         echo "rsync startup ok"
         return $retval
     else
         echo "rsync startup fail"
         return $retval
     fi
 }
 stop(){
     killall rsync
     retval=$?
     if [ $? -eq 0 ]
     then
          echo "rsync stop ok"
                                                                                                  9,1           Top
        return $retval
    else
        echo "rsync restart fail"
        return $retval
    fi
    }
case "$1" in
    start)
        start
        # 为了向外传值
        retval=$?
        ;;
    stop)
        stop
        retval=$?
        ;;
    restart)
        restart
        retval=$?
        ;;  

    *)
        echo "usage:$0 {start|stop|restart}"
        exit 1
esac

想要使用chkconfig(man ckhconfig),找到这些信息

RUNLEVEL FILES
       Each service which should be manageable by chkconfig needs two or more commented lines added to its init.d
       script. The first line tells chkconfig what runlevels the service should be started in by default, as well
       as the start and stop priority levels. If the service should not, by default, be started in any runlevels,
       a  -  should  be used in place of the runlevels list.  The second line contains a description for the ser‐
       vice, and may be extended across multiple lines with backslash continuation.

       For example, random.init has these three lines:
       # chkconfig: 2345 20 80  表示在2345这几个启动级别上 启动顺序排20 停止顺序排80
       # description: Saves and restores system entropy pool for        #              higher quality random number generation.

在脚本首行加入

#!/bin/bash
# chkconfig: 2345 20 80
# description: rsync start stop and restart   

将脚本移动到/etc/init.d/下,并添加执行权限,添加到chkconfig中才能使用

[root@web-01 /server/tools]# mv /etc/init.d/rsync_up.sh /etc/init.d/rsyncd
[root@web-01 /server/tools]# chmod +x /etc/init.d/rsyncd
[root@web-01 /server/tools]# chkconfig --list rsyncd

Note: This output shows SysV services only and does not include native
      systemd services. SysV configuration data might be overridden by native
      systemd configuration.

      If you want to list systemd services use ‘systemctl list-unit-files‘.
      To see services enabled on particular target use
      ‘systemctl list-dependencies [target]‘.

service rsyncd supports chkconfig, but is not referenced in any runlevel (run ‘chkconfig --add rsyncd‘)
[root@web-01 /server/tools]# chkconfig --add rsyncd
[root@web-01 /server/tools]# chkconfig --list rsyncd

Note: This output shows SysV services only and does not include native
      systemd services. SysV configuration data might be overridden by native
      systemd configuration.

      If you want to list systemd services use ‘systemctl list-unit-files‘.
      To see services enabled on particular target use
      ‘systemctl list-dependencies [target]‘.

rsyncd             0:off    1:off    2:on    3:on    4:on    5:on    6:off

更好一些,调用了系统函数,action。并优化了重复停止的输出

#!/bin/bash
# chkconfig: 2345 20 80
# description: rsync start stop and restart
##############################################################
# File Name: syncd.sh
# Version: V1.0
# Author: pizza
# Created Time : 2019-03-29 22:06:46
# Description:
##############################################################
. /etc/init.d/functions
start(){
    rsync --deamon
    retval=$?
    if [ $retval -eq 0 ]
    then
        action  "rsync startup ok" /bin/true
        return $retval
    else
        action "rsync startup fail" /bin/false
        return $retval
    fi
}
                                                1,1           Top
        return $retval
    fi
    }
case "$1" in
    start)
        start
        # 我了向外传值
        retval=$?
        ;;
    stop)
        stop
        retval=$?
        ;;
    restart)
        restart
        retval=$?
        ;;

    *)
        echo "usage:$0 {start|stop|restart}"
        exit 1
esac
     

开发和系统媲美的脚本

                                                         92,0-1        Bot
#!/bin/bash
# chkconfig: 2345 20 80
# description: rsync start stop and restart
##############################################################
# File Name: syncd.sh
# Version: V1.0
# Author: pizza
# Created Time : 2019-03-29 22:06:46
# Description:
##############################################################
# 定义锁文件
lockfile=/var/lock/subsys/rsyncd
# 定义变量,指定rsyncd的的pid,是需要自己rsync的conf中去创建

#[root@web-01 /server/tools]# vim /etc/rsyncd.conf
#pid file=/var/run/rsyncd.pid    

srsync_pid_file_path=/var/run/rsyncd.pid
. /etc/init.d/functions
start(){
    rsync --deamon
    retval=$?
    if [ $retval -eq 0 ]
    then
        action  "rsync startup ok" /bin/true
        touch $lockfile
        return $retval
    else
        action "rsync startup fail" /bin/false
        return $retval
    fi
}
stop(){
    # 为了在重复停止操作的时候,不提示,将其扔到黑洞
    if test -s "$rsyncd_pid_file_path"
    then
        rsyncd_pid=`cat $rsyncd_pid_file_path`
        # 判断进程号是不是真实存在
        if (kill -0 $rsyncd_pid &>/dev/null)
        then
            kill $rsyncd_pid

            retval=$?
            if [ $? -eq 0 ]
            then
                action "rsync stop ok" /bin/true
                rm -f $lockfile
                return $retval
            else
                action "rsync stop fail" /bin/false
                return $retval
            fi
        else
            echo "rsyncd process is not exist."
            return 2
        fi
    else
        echo "$srsync_pid_file_path is not exits,or rsyncd doesnot start"
    fi
}
restart(){
    killall rsync && sleep 1 && rsync --deamon
    retval=$?
    if [ $? -eq 0 ]
    then
        action "rsync restart ok" /bin/true
        return $retval
    else
        action "rsync restart fail" /bin/false
        return $retval
    fi
    }
case "$1" in
    start)
        start
        # 我了向外传值
        retval=$?
        ;;
    stop)
        stop
        retval=$?
        ;;
    restart)
        restart
        retval=$?
        ;;

    *)
        echo "usage:$0 {start|stop|restart}"
        exit 1
esac
  

case总结

1、case语句和if条件句的使用性

case语句比较适合变量较少且为固定的数字或者字符串集合的情况(非不确定内容,如范围)

2、if和case的常用应用场景

case只要写服务的启动脚本,一般情况下,传参不同且具有少量的字符串,其使用范围较窄

if就是取值判断、比较,应用比case更广,几乎所有的case语句都可以用if条件语句实现。

3、case语句的特点和优势

它相当于多分支的if/elif/else语句,但是case语句的优势是更规范。易读

while循环

循环语句命令常用于重复执行一条指令或一组指令,直到条件不满足停止,Shell脚本语言的循环语句常见的有while、until、for以及select循环语句。 while循环语句主要用来重复执行一组命令或语句,在企业实际应用中,常用于守护进程或持续运行的程序,除此以外,大多数循环都会用后文即将讲解 的for循环语句。

while true
do
    uptime >> /tmp/uptime.log
    sleep 2 # 暂停2s
    usleep 2000 # 微秒
done

脚本进程管理命令

后台运行  &、nohup、screen(运维人员)

 为什么要用后台运行,防止你在执行重要命令的时候,网络宕机

进程管理的其他常见命令

范例1:请使用while循环对下面的脚本进行修改,是的当执行脚本时,每次执行完脚本后,不退出脚本,而是提示用户输入

while true
do
    read -p "请输入两个数字:" a b
    if [ -z $b ]
    then
        echo "请输入两个数字"
        continue
    fi
    expr 10 + $a + $b &>/dev/null
    if [ $? -ne 0 ]
    then
        echo "请输入两个数字"
        continue
    fi
    echo "a+b=$(($a+$b))"
done

范例2:猜数字游戏。首先让系统随机生成一个数字,给这个数字定一个范围(1-60),让用户输入猜的数字,对输入进行判断,如果不符合要求,就给予高或低的提示,猜对后则给出猜对用的次数,请用while语句实现。

提示:可以赋予一个猜水果的价格游戏。

1、给数字定范围(1-60)
RANDOM随机数,它的范围是0-32767
[root@web-01 /server/tools]# echo $RANDOM
9279
为随机数取模。控制在1-60
[root@web-01 /server/tools]# echo $((RANDOM%60))
11
2、用户输入数字
read -p “请输入数字:” num

3、对比,直到正确才推出
while
4、代码:
random="$(($RANDOM%60))"
#做计数
count=0
echo $random
while true
do
    read -p "请输入数字:" num
    ((count++))
    if [[ $num -lt $random ]]
    then
        echo "低了"
        continue
    elif [[ $num -gt $random ]]
    then
        echo "高了"
        continue
    elif [[ $num -eq $random ]]
    then
        echo "恭喜你,猜对了,一共猜了$count次"
        exit 0
    else
        echo "请输入数字"
    fi
done

还可以加入函数,其他的限制内判断,使脚本更完善

范例3:分析Apache访问日志(access_2010-12-8.log),把日志中每行的访问字节数对应字段数字相加,计算出总的访问量。给出实现程序,请用while循环实现。(3分钟)

方式1:在while循环结尾done通过输入重定向指定读取的文件。
while read line
do
    cmd
done<FILE
方式2:使用cat读取文件内容,然后通过管道进入while循环处理。
cat FILE_PATH|while read line
do
    cmd
done
方式3:采用exec读取文件后,然后进入while循环处理。
exec <FILE
sum=0
while read line
do
    cmd
done

体验

while read line
do
    echo $line
    sleep 1
done < ./while_01.sh
~
~                                                                        

"while_readline.sh" [New] 13L, 320C written
[root@web-01 /server/tools]# sh while_readline.sh
#!/bin/bash
##############################################################
# File Name: while_01.sh
# Version: V1.0
# Author: pizza
# Created Time : 2019-03-30 07:19:26
# Description:
##############################################################
while true
do
uptime >> /tmp/uptime.log
sleep 2 # 暂停2s
usleep 2000 # 微秒
done

体验2

[root@web-01 /server/tools]# seq 10 >>num.log
脚本
sum=0
while read line
do
    ((sum+=line))

done<./num.log
echo $sum
执行
[root@web-01 /server/tools]# sh while_num_add.sh
55

答案

sum=0
awk ‘{print $10}‘ access_2010-12-8.log |grep -v -|while read line
do
    ((sum+=line))
done
echo sum
# 已经计算了,但是最后的结果是0
# 这是因为执行了子shell
# 使用下面的方法可以成功输出                                             

sum=0
awk ‘{print $10}‘ access_2010-12-8.log |grep -v - > any_sum.log
do
    ((sum+=line))
done<./any_sum.log
echo sum 

小结

1、while循环的特长是执行守护进程,以及实现我们希望循环不退出持续执行的应用

擅长用于频率小于1分钟循环处理,其他的while循环几乎都可以被for以及定时任务crond替代

2、if、for最常用,然后是while(守护进程),case(服务启动脚本)

Shell脚本中各个语句的使用场景

  1、条件表达式,用于简短的条件判断及输出(文件是否存在,字符串是否为空)

  2、if取值判断,多用于不同值数量较少的情况

  3、for正常的循环应用处理,最常用

  4、while多用于守护进程,无限循环(要加sleep,usleep,控制pinlv)应用

  5、case 多用于服务启动脚本,打印菜单可用select语句,不过很少用,都用cat的here文档方法替代

  6、函数用途主要指编码逻辑清晰,减少重复语句开发

for循环

for循环语句和while循环语句类似,但for循环语句主要用于执行次数有限的循环,而不是用于守护进程以及无限循环。for循环语句常见的语法有两种, 下面将在不同的语法中对for循环语句进行详尽的讲解。

..

范例1:用for循环竖向打印1、2、3、4、5共5个数字。
范例2:通过开发脚本实现仅设置sshd rsyslog crond network sysstat服务开机自启动。
范例3:计算从1加到100之和。
范例4:在Linux下批量修改文件名,将文件名中的“_finished”去掉。
准备测试数据,如下。
[root@oldboy test]# mkdir /oldboy -p
[root@oldboy test]# cd /oldboy
[root@oldboy oldboy]# touch stu_102999_1_finished.jpg stu_102999_2_finished.jpg stu_102999_3_finished.jpg
[root@oldboy oldboy]# touch stu_102999_4_finished.jpg stu_102999_5_finished.jpg
[root@oldboy oldboy]# ls -l
总用量 0
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_1_finished.jpg
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_2_finished.jpg
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_3_finished.jpg
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_4_finished.jpg
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_5_finished.jpg

ls *.jpg|awk -F "_finished" ‘{print "mv",$0,$1$2}‘|bash
rename "_finished" "" *.jpg
for file in `ls ./*.jpg`
do
    mv $file `echo ${file/_finished/}`
done

范例1答案

for n in 1 2 3 4 5  或者 {1..5}  或者seq 5
do
    echo $n
done
echo "---------"
for ((i=1;i<=5;i++))
do
    echo $i
done
"for_printnum.sh" [New] 18L, 350C written
[root@web-01 /server/scripts]# sh for_printnum.sh
1
2
3
4
5
---------
1
2
3
4
5

范例2答案

for name in sshd rsyslog crond network sysstat
do
    echo "chkconfig $name on"
done

相当于在命令行执行[root@web-01 /server/scripts]# chkconfig |grep 3:on |awk ‘{print "chkconfig",$1,"off"}‘|bash

范例3

1、for循环
2、while循环
3、算法 

范例4

1、mv $file ‘echo ${file/_finished/}‘
2、不用for循环
[root@web-01 /server/scripts]# ls *.jpg|awk -F "_finished" ‘{print $0,$1$2}‘
3、rename  from  to  file
rename  _finished ""  *.jpg

循环控制语句break、continue、exit、return

在上述命令中,break、continue在条件语句及循环语句(for、while、if等)中用于控制程序的走向,

而exit则用于终止所有语句并退出当前脚本,除此之外,exit还可以返回上一次程序或命令的执行状态值给当前Shell;

return类似exit,只不过return仅用于在函数内部返回函数执行的状态值。

break n    如果省略n表示跳出整个循环,n 表示跳出循环的层数
continue n    如果省略n表示跳过本次循环,忽略本次循环的剩余代码,进入循环的下一次循环。n 表示退到第n层继续循环
exit n    退出当前shell程序,n为上一次程序执行的状态返回值。n也可以省略,再下一个shell里可通过$?接收exit n的n值
return n    用于在函数里,作为函数的返回值,用于判断函数执行是否正确。再下一个shell里可通过$?接收exit n的n值

Shell编程数组应用实践

为什么会产生shell数组

通常在开发Shell脚本时,我们定义变量采用的形式为a=1;b=2;c=3,可如果有多个变量呢?这时再一个一个定义很费劲,并且要是有多个不确定的变量内容,也难以进行变量定义,此外,快速读取不同变量的值也是一件很痛苦的事情,于是数组就诞生了,它就是为了解决上述问题而来的。

什么是Shell数组

如果读者有过其他语言的编程经历,那么想必会熟悉数组的概念。简单地说,Shell的数组就是把有限个元素(变量或字符内容)用一个名字命名,然后用编号对它们进行区分的元素集合。这个名字就称为数组名,用于区分不同内容的编号就称为数组下标。组成数组的各个元素(变量)称为数组的元素,有时也称为下标变量。

有了Shell数组后,就可以用相同名字引用一系列变量及变量值,并通过数字(索引)来识别使用它们。在许多场合,使用数组可以缩短和简化程序开发。

数组的本质还是变量,是特殊的变量形式
array=(1 2 3 4 5)

Shell数组的定义*****
    方法1:推荐,用小括号把变量值括起来赋值给数组变量,中间用空格分割
    array=(one two three four)
    方法2:用小括号把变量值括起来,同时采用键值对的形式赋值
    array=([0]=one [1]=two [2]=three [3]=four)
    方法3:通过分别定义数组变量的方式
    [root@web01 ~]# array[0]=one
    [root@web01 ~]# array[1]=two
    [root@web01 ~]# array[2]=three
    [root@web01 ~]# array[3]=four
    [root@web01 ~]# echo ${array[@]}
    one two three four
    方法4:命令的结果放到数组里,推荐。动态定义数组变量,使用命令的输出结果作为数组的内容
    array=(`ls /server/scripts`)

说明:还可以使用declare -a array来定义数组类型,但是比较少这样用。

操作数组元素
打印单个数组元素用${数组名[下标]},当未指定数组下标时,数组的下标是从0开始。
使用*或者@可以得到整个数组内容。
用${#数组名[@或*]}可以得到数组长度,这和前文讲解的变量子串知识是一样的,因为数组也是变量,只不过是特殊的变量,因此也适合变量的子串替换等知识。

读取数组内容:*****
[root@web01 ~]# array=( 1 2 3 4 5)
[root@web01 ~]# echo ${array[0]}
1
[root@web01 ~]# echo ${array[1]}
2
[root@web01 ~]# echo ${array[2]}
3
[root@web01 ~]# echo ${array[3]}
4
[root@web01 ~]# echo ${array[4]}
5
[root@web01 ~]# echo ${array[5]}

[root@web01 ~]# echo ${array[*]}
1 2 3 4 5
[root@web01 ~]# echo ${array[@]}
1 2 3 4 5
[root@web01 ~]# echo ${#array[@]}
5
[root@web01 ~]# echo ${#array[*]}
5

给数组增加内容:
[root@web01 ~]# array[5]=oldboy   <==增加下标为5的数组元素。
[root@web01 ~]# echo ${#array[*]}
6
[root@web01 ~]# echo ${array[*]}
1 2 3 4 5 oldboy

删除数组元素:
[root@web01 ~]# unset array[1]
[root@web01 ~]# echo ${array[*]}
1 3 4 oldboy
[root@web01 ~]# unset array[0]
[root@web01 ~]# echo ${array[*]}
3 4 oldboy

数组赋值:
[root@web-01 /server/scripts]# array[4]=999
[root@web-01 /server/scripts]# echo ${array[*]}
1 2 3 4 999 6

数组的删除:
因为数组本质上还是变量,因此可通过“unset 数组[下标]”清除相应的数组元素,
如果不带下标,表示清除整个数组的所有数据。
[root@web-01 /server/scripts]# unset array[1]  删除单个元素
[root@web-01 /server/scripts]# echo ${array[*]}
1 3 4 999 6
[root@web-01 /server/scripts]# unset array    删除整个数组
[root@web-01 /server/scripts]# echo ${array[*]} 没有数据输出了

数组内容的截取和替换:
这里和前文变量子串的替换是一样的,因为数组是特殊的变量
[root@web-01 /server/scripts]# echo ${array[*]:1:3}  从下表为1的元素截取3个元素
2 3 4
替换 和sed命令,和变量子字符串的替换 很像,是一样的
[root@web-01 /server/scripts]# echo ${array[*]/1/999}
999 2 3 4 5 6 7 8 9 9990
[root@web-01 /server/scripts]# echo ${array[*]}  该操作不会改变原数组,要改变请参考赋值修改
1 2 3 4 5 6 7 8 9 10

数组也是变量,因此也适合于前面讲解过的变量的子串处理的功能应用。
数组的其他相关知识通过man bash然后搜Arrays来了解。

数组元素部分内容的删除如下:
[root@oldboy data]# array=(one two three four five)
[root@oldboy data]# echo ${array[@]}
one two three four five
[root@oldboy data]# echo ${array[@]#o*}    #<==从左边开始匹配最短的,并删除。
ne two three four five
[root@oldboy data]# echo ${array1[@]##o*}  #<==从左边开始匹配最长的,并删除。
two three four five
[root@oldboy data]# echo ${array[@]%f*}    #<==从右边开始匹配最短的,并删除。
one two three
[root@oldboy data]# echo ${array[@]%%f*}   #<==从右边开始匹配最长的,并删除。
one two three

使用for循环打印数组元素
array=(1 2 3 4 5)
for n in ${array[*]}
do
    echo $n
done
echo =====================
#i为数组下标
for ((i=0;i<${#array[*]};i++))
do
    echo ${array[i]}
done 

array=([1]=one [2]=two [3]=three)
array[0]=a;array[1]=b;array[2]=c
array=($(命令))
或
array=(`命令`)

shell数组企业面试题

1、利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。

I am pizza teacher welcome to luffy training class

array=(I am oldboy teacher welcome to oldboy training class)

for word in ${array[*]}#或者#for ((i=0;i<=${array[*];i++}))
do
    if [ ${#word} -lt 6  ]  # if [ ${#array[i]} -lt 6 ]
    then
        echo $word   # echo array[i]
    fi
done

    

第十四章 编程规范
第十五章 脚本调试
第十六章 vim配置
第十七章 trap
第十八章 expect
第十九章 企业案例实战

第十九章
企业面试题1:
分析:
1、获取随机小写字符。
echo $RANDOM$(date +%N)|md5sum|tr "[0-9]" "a-z"|cut -c 2-11

2、for循环

企业面试题3:
1、01..10
[root@db03 ~]# seq -w 10
01
02
03
04
05
06
07
08
09
10
[root@db03 ~]# echo ${01..10}
-bash: ${01..10}: bad substitution
[root@db03 ~]# echo {01..10}
01 02 03 04 05 06 07 08 09 10

2、echo $RANDOM|md5sum|cut 1-8
3、for循环批量设置用户和密码。

企业面试题4:

1、如何判断机器是否是活的。
ping 10.0.0.53 -c 2 -W 3 有返回。
nmap -sP 10.0.0.0/24

2.for循环

#!/bin/sh
CMD="nmap -sP"
Ip="10.0.0.0/24"
$CMD $Ip|awk ‘/Nmap scan report for/ {print $NF}‘

http://blog.51cto.com/oldboy/1632876
10,11,18,19,20,13,6

原文地址:https://www.cnblogs.com/yxiaodao/p/10612026.html

时间: 2024-07-31 11:30:56

shell编程企业级实战(2)的相关文章

shell编程企业实战(试题)

1. 写一个脚本,实现批量添加20个用户,用户名为user1-20,密码为user后面跟5个随机字符 2. Shell实用案例:批量生成随机字符文件 3.请用至少两种方法实现! 将以上文件名中的oldboy全部改成oldgirl(用for循环实现),并且html改成大写. [[email protected] ~]# ll /oldboy/ total 0 -rw-r--r-- 1 root root 0 Jul 20 20:45 aebccciiaj_oldboy.HTML -rw-r--r-

Linux运维都要会哪些shell编程技能?

在充斥着各种的互联网+的数字时代,Linux运维也越来越趋于自动化方向发展,越来越多的运维工作者奔跑在了自动化运维的路上.目前Linux系统下最流行的运维自动化语言就是shell和Python了. 两者之间,shell几乎是IT企业必须使用的运维自动化编程语言,特别是在运维工作中的服务监控.业务快速部署.服务启动停止.数据备份及处理.日制分析等环节里,shell是不可缺的.当然Python也是一门更适合处理复杂的业务逻辑,以及开发复杂的运维软件工具,实现通过web访问等.Shell是一个命令解释

京峰Linux Shell编程从入门到精通

课程介绍:Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口.它接收用户输入的命令并把它送入内核去执行. -------------------课程目录------------------- <Shell编程从入门到精通> ├1.linux下shell编程基础入门_(new).mp4├2.Shell编程之变量及LAMP导航菜单编写_(new).mp4├3.Shell编程之IF条件语句各种案例演练_(new).mp4├4.使用if条件语句编写MySQL备份脚本_(new).mp4

Shell编程(3)

1. shell流程控制 2. for语句 3. while语句 4. break和continue语句 5. case语句 6. shell编程高级实战 shell流程控制 流程控制是改变程序运行顺序的指令.linux shell有一套自己的流程控制语句,其中包括条件语句(if),循环语句(for,while),选择语句(case).下面我将通过例子介绍下,各个语句使用方法 if语句 格式: 格式:if list; then list; [ elif list; then list; ] ..

老男孩新书Shell编程实战预定开始了-包邮包答疑

老男孩新书Shell编程实战预定开始了(扫图中二维码购买包邮定期包答疑),亲爱的伙伴们,让你们久等了.电脑用户猛戳 电脑购买链接 注意:包邮包3个月(2017春节后起算)Q群书籍内容答疑,等于白送书,还倒搭答疑服务. 如果觉得给力,请帮忙朋友圈.QQ群.空间转载! 活动优惠仅限本次活动,从其他渠道购买不享受此次的服务承诺. 定价 89元 基本信息 作者: 老男孩 丛书名: Linux/Unix技术丛书 出版社: 机械工业出版社 ISBN:9787111556077 上架时间:2017-1-6 出

Linux系统shell脚本编程——生产实战案例

Linux系统shell脚本编程--生产实战案例     在日常的生产环境中,可能会遇到需要批量检查内网目前在线的主机IP地址有哪些,还可能需要检查这些在线的主机哪些端口是开放状态,因此依靠手工来检查是可以实现,但比较费时费力,所以需要结合shell脚本来实现批量检查的功能,那么今天就来做个小小的实验. 1.开发脚本前准备 一般大家都知道,测试主机是否在线,常用的命令无非就是ping.nmap,因此,首先找一个地址来测试下ping命令的效果 [[email protected] scripts]

《跟老男孩学Linux运维之shell编程实战》-第二章 shell变量的核心基础

这篇文章主要讲解 shell变量的核心基础. 1.变量是什么? 变量是什么?可能有好多人不明白,简单地说,变量就是用一个固定的字符串(也可能是字符.数字等的组合)代替更多.更复杂的内容,该内容里可能还会包含变量.路径.字符串等其他的内容. 变量的赋值方式为:先写变量名称,紧接着是"="这个字符,最后是值,中间无任何空格(变量的内容一般要加双引号,以防止出错,特别是当值里的内容之间有空格时). 如何打印变量?通过echo命令加上$变量名 打印变量的值: 例如:定义变量和打印变量: [[e

《跟老男孩学Linux运维之shell编程实战》-第五章 shell脚本的条件测试

本文的知识点是关于shell脚本的条件测试的相关内容. 通常在shell脚本中我们需要做各式各样的条件判断,比如,测试一个文件是否存在.是否为文件或目录.是否 具有执行权限等等,所以在shell脚本中,条件判断还是至关重要的.接下来我们进入正题:shell脚本的条件测试. 1.在bash编程中,条件测试常用的语法形式如下表: 提示: 语法1中的test命令和语法2中的[]是等价的.语法3中的[[]]双中括号为扩展的test命令. 语法4中的(())常用于计算. 在双中括号[[]]中可以使用通配符

《跟老男孩学Linux运维之shell编程实战》-第四章 变量的数值计算

本文讲解shell编程中变量的数值计算. 1.常见的算术运算符: 提示: 此处对于我自己来说++.--比较难理解,之前一看到脚本中有这些符号,就看不懂了,所以在此举例说明一下: [[email protected] ~]# a=10                  ==>定义变量a[[email protected] ~]# echo $((a++)) ==>如果a在运算符++或--的前面,那么输出整个表达式时,会输出a的值, 此前定义的变量a为10,所以此处的值为10.10[[email