Shell脚本(三剑客 sed、awk、grep 案例)

1、删除和替换文件中某一行的方法

介绍:sed 、grep 、awk
sed:本身是一个管道命令,主要以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定作                            
常用选项:
 -n∶使用sed 都会被列出到萤幕上,查询特定的内容会出现重复。但如果加上 -n 参数后,则只有经过sed 特殊处理的那 一行(或者动作)才会被列出来。

[root@localhost home]# sed '/HWADDR/p' b.txt
   TYPE=Ethernet
   HWADDR=00:0c:29:de:30:bb
   HWADDR=00:0c:29:de:30:bb
   BOOTPROTO=static
   DEVICE=eth1
  [root@localhost home]# sed -n  '/HWADDR/p' b.txt 
   HWADDR=00:0c:29:de:30:bb       

       -e∶直接在指令列模式上进行 sed 的动作编辑;
        -f∶直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作;
        -r∶sed 的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法)
        -i∶直接修改读取的档案内容,而不是由萤幕输出。    

常用命令:
        a   ∶新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
        c   ∶取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
        d   ∶删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
         i   ∶插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
         p  ∶列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作~

查询包含模式的行/p ,可以达到模糊匹配,/HWADDR/p, 找到有关HWADDR的行
/I 标识不区分大小写,如sed  's/ /Ig' ifcfg-eth1 替换不区分大小写
[root@localhost home]# sed -n '/HWADDR/Ip' ifcfg-eth1
 HWADDR=00:0c:29:de:30:bb     

         s  ∶取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!

s/\(HWADDR\).*/'HWADDR=`echo 123`'/Ig' ifcfg-eth1
用sed  's/\(关键字 \).*/\1hello/'会把所有title后面的字符都替换掉,变成

脚本1:通过ifcong -a 中的mac地址修改ifcong-eth[root@localhost home]# cat c.sh 

#/bin/bash

read -p "输入要修改的网卡信息,如eth0:" name
cd /etc/sysconfig/network-scripts
grep -i 'HWADDR' ifcfg-$name
   if [ $? -eq 0 ];then
      a=`ifconfig -a $name |grep ether| awk '{print $2}'`
      sed -n '/HWADDR/Ip' ifcfg-$name | sed -i -e 's/\(HWADDR\).*/'HWADDR=`echo $a`'/Ig' ifcfg-$name
   else 
      echo HWADDR=$a >>ifcfg-eth1
  fi 

grep: grep -i  grep默认对字母大小写敏感,不过可以通过选项对grep屏蔽。

脚本2:问题:[[$i=~^[0-9]+$]]&&echo1的意思是:

[[ ]]         条件判断语句
$i            i是个变量,$i代表读取变量i的值
=~            正则匹配,用来判断其左侧的参数是否符合右边的要求
^             以什么开头
^[0-9]        以数字开头,表示0到9的数字,只有一个数字
^[0-9]+       以数字开头,且数字至少一个    加号表示不知一个
$             以什么结尾
^[0-9]+$      数字至少一个数字开头,并且过程会匹配到结尾。意即:只能有数字,不能有其他字符
&&            左边的条件满足,右边的命令才会执行。
echo 1        屏显1(在屏幕上显示,也叫打印)

所以:[[$i=~^[0-9]+$]]&&echo1的意思是:变量i的值是纯数字,就屏显1


SHELL中的通配符:

*                   匹配任意长度的任意字符,可以是0个,匹配多个文件需要加单引号或者双引号
?                   匹配任意单个字符,必须是1个
[list]              匹配list中单一字符,[!list]匹配处list中的单一字符 
                       如 j[av]a   等价于 jaa jva
[a-z]               匹配[a-z]中任意单一字符,[0-9]同理
{a..z}              匹配a到z中间所有字符,{1..30}同理
[ ]                 匹配指定字符范围内的任意单个字符
[a-z,A-Z,0-9]       匹配所有数字字母,可以不加逗号
[a-z]               表示a-z,A-Y,表示a,A,b,B.....a。不包含Z
[A-Z]               表示A,b,B.....z,Z。不包含a
[a-Z]               表示所有大小写字母
[:upper:]           所有大写字母
[:lower:]           所有小写字母
[:alpha:]           所有字母,大小写
[:digit:]           所有数字
[:alnum:]           所有数字+字母
[:blank:]           水平空白字符
[:space:]           水平或垂直空白字符
[:punct:]           标点符号
[:print:]           可打印字符
[:cntrl:]           控制(非打印)字符
[:graph:]           图形字符
[:xdigit:]          十六进制字符
[^]                 匹配指定字符范围外的任意单个字符
[^0-9]              相当于[^[:digit:]]
[^a-z]              表示Z + 其他
[^A-Z]              表示a + 其他


正则表达式:
[\d] 等价于 [0-9]
{0,1}         表示0或或1个,即有或没有的意思,等价于正则中的?[0-9]{0,4}:

脚本3:shell编程取AAA=(1.rpm 2.rpm 3.rpm 4.rpm) 里面有多少.rpm

 b=${#AAA[@]}
 echo $b

做成for循环,输出每一个数值
for(( i=0;i<${#AAA;i++))   
do
	echo ${AAA[i]};
done;	

查看tomcat 版本
/usr/local/tomcat/bin/./version.sh  >/mnt/tomcatv.txt

脚本4:   +,*,[:space:]的一些用法

+ 匹配1个或多个字符
* 匹配0个或多个字符,匹配多个文件需要加单引号或者双引号
[:space:] 匹配空白字符,包括空格,tab

文件file是含有多个空格和tab的几行字符,下面将以file文件为例做几个简单的实验
[root@node1 ~]# cat file
     5
 5
  5
5
          5
           5

方法1:删除空格
[root@node1 ~]# sed 's/ *//g' file       空格*:  匹配空格0个或多个字符
[root@node1 ~]# sed 's/[ ]*//g' file
5
5
5
5
5
5
[root@node1 ~]#

方法2:删除空格
[root@node1 ~]# sed 's/ +//g' file        空格*:  匹配空格1个或多个字符
     5
 5
   5
5
            5
              5
没有起作用,+转义以后可以删除空格,转义字符\
[root@node1 ~]# sed 's/ \+//g' file
5
5
5
5
5
5

方法3:删除空格
[root@node1 ~]# sed 's/[[:space:]]//g' file
5
5
5
5
5
5
[root@node1 ~]#
删除所有的空白字符,包括tab

sed删除行首的空格
leslie@Notebook:/etc/apt$ sed 's/^[[:space:]]*//g' sources.list
#sed 's/^[ ]*//g' test
#sed 's/^ *//g' test 
#sed 's/^[[:space:]]*//g' test


sed删除空行  ,测试没好使
leslie@Notebook:/etc/apt$ sed '/^$/d' sources.list

 

linux cut 命令详解

cut
cut命令可以从一个文本文件或者文本流中提取文本列。
cut语法
[root@www ~]# cut -d'分隔字符' -f fields <==用于有特定分隔字符
[root@www ~]# cut -c 字符区间            <==用于排列整齐的信息
选项与参数:
-d  :后面接分隔字符。与 -f 一起使用;
-f  :依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思;
-c  :以字符 (characters) 的单位取出固定字符区间;

PATH 变量如下
[root@www ~]# echo $PATH
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games
# 1 | 2       | 3   | 4       | 5            | 6            | 7

将 PATH 变量取出,我要找出第五个路径。
#echo $PATH | cut -d ':' -f 5
/usr/local/bin

将 PATH 变量取出,我要找出第三和第五个路径
#echo $PATH | cut -d ':' -f 3,5
/sbin:/usr/local/bin

将 PATH 变量取出,我要找出第三到最后一个路径。
echo $PATH | cut -d ':' -f 3-
/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games

将 PATH 变量取出,我要找出第一到第三个路径。
#echo $PATH | cut -d ':' -f 1-3 
/bin:/usr/bin:/sbin:

将 PATH 变量取出,我要找出第一到第三,还有第五个路径。
echo $PATH | cut -d ':' -f 1-3,5
/bin:/usr/bin:/sbin:/usr/local/bin

实用例子:只显示/etc/passwd的用户和shell
#cat /etc/passwd | cut -d ':' -f 1,7 
root:/bin/bash
daemon:/bin/sh
bin:/bin/sh

"==“和”-eq"的区别
"=="是判断字符串是否相等。
"-eq"是判断字符串对应的数字值是否相等。也就是123这个数值等不等于0123=0+123

#!/bin/bash
num1=123	#num1是长度为3的字符串
num2=0123	#num2是长度为4的字符串

echo "======================================"

echo -n "用==比较时:"
if [ $num1 == $num2 ]
then
	echo "$num1和$num2相等"
else
	echo "$num1和$num2不相等"
fi

echo "======================================"

echo -n "用-eq比较时:"
if [ $num1 -eq $num2 ]
then
	echo "$num1和$num2相等"
else
	echo "$num1和$num2不相等"
fi

结果一目了然
======================================
用==比较时:123和0123不相等
====================================== 
用-eq比较时:123和0123相等

“=”既适用于数字,又适用于字符串
“-eq”偏向整数数字,不能进行字符串的测试判断

脚本5:文件内部指定行(首行、末尾行等)插入内容

1、在文件的首行插入指定内容:
[root@ jerry7-11 ~]# sed -i "1i#! /bin/sh -" a 
执行后,在a文件的第一行插入#! /bin/sh -

2、在文件的指定行(n)插入指定内容:
[root@ jerry7-11 ~]#   sed -i "niecho "haha"" a 
执行后,在a文件的第n行插入echo "haha"
如sed -i "2isearch host.com"  /etc/resolv.conf
在第一行下加入search host.com

3、在文件的末尾行插入指定内容:
用第二种方法也可以。一般实现:
[root@ jerry7-11 ~]#   echo “haha” >> a
执行后,在a文件的末尾行插入haha

脚本6: 实现如果输入有问题,提示后再输入嵌套

#/bin/bash

ipxunh(){
while true
do
           b=`echo $ip |tr -cd . |wc -c`
           [ 3 == $b ]
           if [ $? -eq 0 ];then
              for((i=1;i<$b;i++))
               do
                if [ `echo $ip |cut -d '.' -f $i` = "" ];then
                       echo "输入的路径有误格式为:mun.mun.mun.mun" && ipxunh2
                fi
               done
              break
           else
               echo "输入的路径有误格式为:mun.mun.mun.mun" && ipxunh2
           fi
done
}
ipxunh2(){
read -p "输入ip:" ip
ipxunh $ip;
}
read -p "输入ip:" ip
ipxunh $ip;
echo "您输入的IP为" $ip
read -p "用户名:" user
read -p "密码:" passwd

portxunh(){
while true  
do 
           grep '^[[:digit:]]*$' <<< "$port" >/dev/null
           if [ $? -eq 0 ];then 
              break 
           else 
              echo "输入的端口格式有误,非数字" && portxunh2 
           fi
done 
}
portxunh2(){
read -p "端口号:" port
portxunh $port;
}
read -p "端口号:" port
portxunh $port
echo "您输入的端口号为" $port

#测试连接状态
mysql -u$user -p$passwd -h$ip -P $port -e ";" >/dev/null
if [ $? -eq 0 ];then
  echo "连接正常"
else 
  echo "连接失败" && exit
fi

read -p "数据库名字:" db
wayxunh(){
while true
do
           i=1
           read -p "恢复数据库的文件路径:" way
           echo $way |grep /
           if [ $? -eq 0 ];then
               b=`echo $way |grep -o / |wc -l`
               for i in $b
               do
                if [ `echo $way |cut -d '/' -f $i` = "" ];then
                       echo "输入的路径有误格式为:/路径/路径" && wayxunh
                 else
                fi
               done
               break
           else
               echo "输入的路径有误格式为:/路径/路径" && wayxunh
           fi
}
wayxunh

echo $user
echo $passwd
#mysql -u$user -p$passwd $db -h$ip -p$port <$way

脚本7: SHELL 在指定行的前/后插入指定内容

#sed 默认不改变文件,修改后加载内存中,并打印桌面。修改源文件sed -i 会输出到STDOUT

测试例子:
[root@localhost ~]# cat my.cnf 
aaaa
mysql_sock
cccc

[root@localhost ~]# cat a.txt 
aaaa
bbbb

一、已知行数:

1.1 在第几行下插入: 第三行下添加字符TJ2
[root@localhost ~]# sed '3i\TJ2' my.cnf 
aaaa
mysql_sock
TJ2
cccc

1.2 在第几行下插入多条: 第三行下添加字符TJ1,在TJ1行下就是第五行添加字符TJ2
[root@localhost ~]# sed '3i\TJ1\nTJ2' my.cnf  
aaaa
mysql_sock
TJ1
TJ2

cccc

1.3 把a.txt插入my.cnf第二行下
[root@localhost ~]# sed '2 r a.txt' my.cnf
aaaa
mysql_sock
aaaa
bbbb

cccc

1.4 把a.txt插入my.cnf第二行下    没测试
awk '1;NR==2{system("cat a.txt")}'  my.cnf > my.cnf

二、已知参数、未知行数:

1.1 匹配到某一个字符串下添加:  a(下)
在遇到的每一个mysql_sock行的下面添加一行内容为xiaowu
[root@localhost ~]# sed '/mysql_sock/a\xiaowu' my.cnf 
aaaa
mysql_sock
xiaowu
cccc

在遇到的每一个mysql_sock行的下面添加多行内容
[root@localhost ~]# sed '/mysql_sock/a\xiaowu\nxiaoming\nxiaoliu' my.cnf 
aaaa
mysql_sock
xiaowu
xiaoming
xiaoliu

cccc
[root@localhost ~]#

1.2 匹配到某一个字符串下添加:  i(上)
在遇到的每一个mysql_sock行的上面添加多行内容
[root@localhost ~]# sed '/mysql_sock/i\xiaowu\nxiaoming\nxiaoliu' my.cnf 
aaaa
xiaowu
xiaoming
xiaoliu

mysql_sock
cccc

1.3 匹配到某一个字符串下添加:  
[root@localhost ~]# sed '/aaaa/ r a.txt' my.cnf 
aaaa
aaaa
bbbb

mysql_sock
cccc

1.4 匹配到某一个字符串下添加: 没测试
awk '/aaaa/{system("cat a.txt")}' my.cnf >my.cnf

1.5 向指定行的末尾添加指定内容,比如在“ccccc”行的行尾添加“ eeeee”
[root@xiaowu shell]# cat file
ccccc
[root@xiaowu shell]# sed 's/cc.*/& eeeee/g' file
ccccc eeeee

三、获取某一个字符串行号的方法:

获取第二个“bbbb”行的行号的方法:
方法一:
cat -n my.cnf |grep b |awk '{print $1}'|sed -n "2"p my.cnf 
方法二:
sed -n '/bbbb/=' file |sed -n "2"p my.cnf 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值