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
cccc1.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