day19:打印文档中只有一个数字的行|实习日记归档功能|统计一个网段内在线IP|检查脚本错误退出及编辑|随机数字按千分为输出

感情迁移 提交于 2020-02-29 22:07:32

1、用shell脚本把一个文本文档中只有一个数字的行给打印处理;准备一下test.txt文件用来测试,内容如下:

[root@localhost_001 ~]# cat test.txt 
aaa:1:abcde:sdfsd:sdfasd
bbb:22:adsafsadfsdaf:sdafsd
bbb:2:233:3sdfsdf
分析:既然要只有一个数字的行,也就是要针对每一行去逐行去处理,此处用到了for循环或者while分别处理每一行;

判断某行有一个数字,可以这样来实现: 过滤出非0-9的内容替换为空,并统计字符长度;     sed  's#[^0-9]##g'|wc  -L

[root@localhost_001 ~]# sed -n '1'p test.txt|sed 's#[^0-9]##g'|wc -L
1
[root@localhost_001 ~]# sed -n '2'p test.txt|sed 's#[^0-9]##g'|wc -L
2
[root@localhost_001 ~]# sed -n '3'p test.txt|sed 's#[^0-9]##g'|wc -L
5

首先统计出文件的行数,  wc -l  test.txt|awk '{print $1}'

[root@localhost_001 ~]# wc -l test.txt
3 test.txt
[root@localhost_001 ~]# wc -l test.txt|awk '{print $1}'
3

然后使用for 来循环打印出每一行,并计算每一行字符长度:

for a in  `seq  1  $n`;do n1=`sed -n 'a'p /root/test.txt|sed 's#[^0-9]##g'|wc -L`   

再用 if 来判断是否等于 1,等于则打印,符合题意要求;  if [ $n1 -eq 1 ] then  sed -n "a"p  /root/test.txt

脚本内容如下:执行后只有第一行有一个数字,故第一行符合要求;

[root@localhost_001 ~]# cat 36.sh 
#!/bin/bash
f=/root/test.txt
n=`wc -l $f|awk '{print $1}'`
for a in `seq 1 $n`
do 
    n1=`sed -n "$a"p $f|sed 's#[^0-9]##g'|wc -L`
    if [ $n1 -eq 1 ]
    then
        sed -n "$a"p $f
    fi
done
执行脚本:
[root@localhost_001 ~]# sh 36.sh 
aaa:1:abcde:sdfsd:sdfasd

其实这个脚本还有第二种方式:使用while  read  line  do   done 的方式逐行处理;

[root@fenye2019 shell]# cat 36.1.sh 
#!/bin/bash
while read line
do
   n=`echo $line|sed 's#[^0-9]##g'|wc -L`
   if [ $n -eq 1 ]
   then
       echo $line
   fi
done < test.txt
执行脚本:
[root@fenye2019 shell]# sh 36.1.sh 
aaa:1:abcde:sdfsd:sdfasd

2、用一个shell脚本,实现日记的切割、归档功能; logrotate

要求日记每天 来归档,1.log,第二天变成了1.log.1  第三天变成了1.log.2  第四天变成了1.log.4  第五天变成1.log.5  只保存5个,后面的删除;

首先在创建一个目录,并在目录下创建对应的几个文件:  1.log   1.log.1  1.log.2  1.log.3  1.log.4  1.log.5

前提在最后还需要重启服务,以保证可以生成新的1.log

[root@fenye2019 shell]# ls /data/logs/
1.log  1.log.1  1.log.2  1.log.4  1.log.5

脚本内容如下: 执行后还需要重启服务,才会生成新的1.log文件;

这个脚本需要倒着推,先处理1.log.5,最后处理1.log.1,先判断1.log.5如果存在的话则删除1.log.5,然后循环遍历为倒序,从5开始循环,然后是4,然后是3,最后是2,之所以不循环1,是因为改名字的是1.log,而不是1.log.0。

在每次把前一个文件(1.log.1)改名成后一个(1.log.2)文件时,最后检测一下这个文件是否存在,如果存在则先删除掉,这样才能顺利把前面文件改名为后面文件,所有使用一个函数mv_log最合适;

[root@fenye2019 shell]# cat 37.sh 
#!/bin/bash
cd /data/logs
log=1.log
mv_log()
{
    [ -f $1 ] &&  mv $1 $2 
}
[ -f 1.log.5 ] && rm -f 1.log.5
for i in `seq 4 -1 1`
do
    j=$[$i+1]
    mv_log $log.$i $log.$j
done
mv 1.log  1.log.1
执行脚本:
[root@fenye2019 shell]# sh 37.sh
[root@fenye2019 shell]# ls /data/logs/
1.log.1  1.log.2  1.log.3  1.log.5

如图脚本所示:   seq  4  -1  1     会倒序输出

[root@fenye2019 shell]# seq 4 -1 1
4
3
2
1

 

3、写一个shell脚本,把192.168.149.0/24网段在线的IP和不在线都列出来,并输出到up.list和down.list两个文件;

分析:ping一个网段时,前面部分(192.168.149)是一样的,最后一位可以用变量代替;

然后可以用ping选项,ping通则这个主机是在线的;ping  -c2  -w2  192.168.149.129   表示ping两个包,每个表间隔2秒;

然后以判断返回值的方式来查看是否可以ping 通;            if  [  $? -eq 0 ]  then  fi

脚本内容如下:

[root@localhost_002 shell]# cat 38.sh 
#!/bin/bash
for i in `seq 1 254`
do
    ping -w2 192.168.149.$i >/dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo "192.168.149.$i" >> /tmp/ip_up.list
    else
        echo "192.168.149.$i" >> /tmp/ip_down.list
    fi
done
执行脚本:
[root@localhost_002 shell]# sh 38.sh 
[root@localhost_002 shell]# cat /tmp/ip_up.list 
192.168.149.2
192.168.149.130
192.168.149.135
[root@localhost_002 shell]# head -n3 /tmp/ip_down.list 
192.168.149.1
192.168.149.2
192.168.149.3

或者可以通过不判断返回值,直接在for循环里用if 来判断即可,如下 :

#!/bin/bash
for i in `seq 1 254`
do
    if ping -c2 -W2 192.168.149.$i >/dev/null 2>/dev/null
    then
        echo "192.168.149.$i" >> /tmp/ip_up.list
    else
        echo "192.168.149.$i" >> /tmp/ip_down.list
    fi
done

4、一个shell脚本,检查指定的shell脚本是否有错误,若有错误,首先显示错误信息,然后提示用户输入q或者Q退出脚本,输入其他内容则用vim打开这个脚本;

分析:要检查脚本是否有错误,使用  sh  -n   脚本名   来测试;               sh  -n  39.sh

提示用户输入read  -p "please input  q/Q exit, or  others  to edit it by vim:" n

需要考虑到 如果变量为 空时,     也是使用 vim 来打开这个文件;          if  [ -z $n ]  then   vim  $i   fi          注: $i  表示第一个参数; 

然后需要判断 $n 是否等于 q 或者 Q,然后执行相应操作:  

 if  [ $n == "q" -o $n == "Q" ]         等同于                   if  [ $n == "q" ] || [ $n =="Q" ]

脚本内容如下:首先定义有语法错误的脚本:然后用来测试:

[root@fenye2019 shell]# cat 1.sh 
#!/bin/bash
#打印出1-50的随机数10次;
for i in `seq 1 10`
     do 
     echo $[RANDOM]
#done
[root@fenye2019 shell]# cat 39.sh
#!/bin/bash
sh -n 2>/tmp/trr
if [ $? -ne 0 ]
then
    cat /tmp/trr
    read -p "please input q/Q to exit:" n
    if [ -z "$n" ]
    then
        vim $1
        exit
    fi
    if [ $n == q ] || [ $n == Q ]
    then
        exit
    else
        vim $1
        exit
    fi
else 
    echo "脚本$1没有语法错误"
fi
执行脚本:  脚本1.sh有语法错误,脚本31.sh没有语法错误;
[root@fenye2019 shell]# sh 39.sh 1.sh
1.sh: line 7: syntax error: unexpected end of file
please input q/Q to exit:q
[root@fenye2019 shell]# sh 39.sh 31.sh
脚本31.sh没有语法错误

注释:在shell脚本中 vim 一个文件,虽然可以进入到这个文件里,但当退出这个文件后,脚本依然会继续执行,所有在 vim $1 命令后面要加上 exit

5、输入一串随机数字,然后按千分位输出;

比如输出:123456789     输出为123.345.769

分析:用户输入: read  -p   "please input a number:" n 来实现:

需要判断用户输入的是否是纯数字,如果不是,则重新输入:   n2=`echo $n|sed '[0-9]'`           if  [ -n $n2 ]  then echo "你输入不是数字,重新输入" continue

脚本内容:

[root@fenye2019 shell]# cat 40.sh 
#!/bin/bash
n=`echo $1|wc -L`
for d in `echo $1|sed 's/./& /g'`
do
    n2=$[$n%3]
    if [ $n2 -eq 0 ]
    then
        echo -n ",$d"
    else
       echo -n "$d" 
    fi
    n=$[$n2-1]
done|sed 's/^,//g'
echo 
执行:
[root@fenye2019 shell]# sh 40.sh 1234567
1,234,567

 注释:默认字符串分割是没有空格的,那么如何变成 以 空格分割 字符串呢?如下:

[root@fenye2019 shell]# echo "1234"
1234

[root@fenye2019 shell]# echo "1234"|sed 's#.#& #g'
1 2 3 4 

然后每一次除以 3 取余数,如果余数为 0 ,则表示可以整除,则用 if 判断,并在前面加,逗号,如果不为 0 ,则不在前面加,逗号;

因为我们是倒序的,还需要在重新计算 n, n=$[$n-1]

最后还需要加上 echo 换行符才可以的;

如果添加的参数 刚刚是 9 位,则最前面还是会显示出来一个 ,逗号,如下:

[root@fenye2019 shell]# sh 40.sh 123523424
,123,523,424
可以在最后在处理一下,过滤到前面的,逗号,              done |sed 's#^,##g'

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!