目录
一、grep
常见参数:
-i: 忽略大小写。
-v: 反向匹配,输出不包含模式的行。
-n: 在每一行前面加上行号。
-r or -R: 递归方式在所有文件中搜索。
-E: 使用扩展正则表达式。
-P: 使用 Perl 兼容的正则表达式。
-o: 仅输出匹配模式的部分。
-l: 仅输出包含匹配行的文件名。
-e: 指定多个搜索模式。
-A数字 #列出符合条件的行,并连续列出后续n行(如果小写,列出前后n行)。
-B数字 #列出符合条件的行,并连续列出前面n行(如果小写,列出前后n行)。
-C数字 #列出符合条件的行,并连续列出前后n行(如果小写,列出输出匹配模式的行数。)
例:
grep -i 'pattern' file.txt
二、sed
1. 命令格式:
sed [选项] ‘[动作]’ 文件名
常见参数:
-n 一般sed命令会把所有数据都输出到屏幕,如果加入此选项,则只会把经过sed命令处理的行输出到屏幕。
-e 允许对输入数据应用多条sed命令编辑。
-f 脚本文件名 从sed脚本中读入sed操作。和awk命令的-f非常相似。
-r 在sed中支持扩展正则表达式。
-i 用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出动作。
输出动作:
a 追加,在当前行后添加一行或多行。添加多行时,除最后一行外,每行末尾需要用\代表数据未完结。
c 行替换,用c后面的字符串替换原数据行。替换多行时,除最后一行外,每行末尾需要用\代表数据未完结。
i 插入,在当前行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用\代表数据为完结。
d 删除,删除指定的行。
p 打印,输出指定的行。
s 字符串替换,用一个字符串替换另外一个字符串。格式为“行范围s/旧字串/新字串/g”(和vim中替换格式类似)
2. 输出指定行
sed '2p' cj.txt
ID Name gender Mark
1 zhaosan M 87.12
1 zhaosan M 87.12
2 lisi M 90.123
3 wangwu M 89.1233322
#只输出了cj.txt中的第二行(-n只输出sed进行的操作)
sed -n '2p' cj.txt
3. 删除指定行
#删除第一行到第三行的数据(只输出到终端,不实际进行删除)
sed '1,3d' cj.txt
#直接处理文件
sed -i '1,3d' cj.txt
4. 添加指定行
#在第四行后加入hello(只输出到终端,不直接处理文件)
sed '4a hello' cj.txt
#在第四行前加入hello(只输出到终端,不直接处理文件)
sed '4i hello' cj.txt
#在第二行前面插入两行数据
sed '2i hello \
> world' cj.txt
#直接处理文件
sed -i '4a hello' cj.txt
5. 替换指定行
#替换第三行(只输出到终端,不直接处理文件)
cat cj.txt | sed '3c No such preson'
#直接处理文件
sed -i '3c No such preson' cj.txt
6. 字符串替换:
#替换第五行中出现的第二个old为new
sed '5s/old/new/2' test.txt
#第四行中,把89换成90
sed '4s/89.1233322/90/g' cj.txt
#替换指定文件中含有SELINUX行中的enforcing字符串为disabled。
sed '/SELINUX/ s/enforcing/disabled/g' /etc/selinux/config
#替换指定文件中所有enforcing为disabled但是不包括含有SELINUX的行。
sed '/SELINUX/ !s/enforcing/disabled/g' /etc/selinux/config
#从含有root的行开始到含有swap的字符串结束。匹配结果中带有xfs的字符串全部替换成ext4。使用行内字符串确定替换字符串的范围。
sed '/root/,/swap/ s/xfs/ext4/g' /etc/fstab
#第二行行首添加注释
sed '2s/^/#/g' cj.txt
#第1-3行添加注释
sed '1,3s/^/#/g' cj.txt
#把zhaosan、wangwu删除
sed -e 's/zhaosan//g ; s/wangwu//g' cj.txt
三、awk
awk使用格式:awk '条件1{动作1} 条件2{动作2}' 文件名
条件(Pattern):
一般使用关系表达式作为条件。这些关系表达式非常多。
例如:x>10 判断变量x是否大于10
x == y 判断变量x是否等于y
A !~ B 判断字符串A是否不包含能匹配B表达式的字符串
动作(Action):
格式化输出
流程控制语句
1.基本使用
awk -F ":" '{ print $1 "\t" $3}' /etc/passwd
#以:为分隔符,输出/etc/passwd的第二列和第三列。
2.awk条件
(1)保留字
BEGIN
在awk程序一开始,未读取任何数据之前执行BEGIN后的动作只在程序开始执行一次。
END在awk程序处理完所有数据,即将结束执行。END后的动作只在程序结束时执行一次。
例:
[root@localhost ~]# awk 'BEGIN {printf "This is a cj \n"} {printf $2 "\t" $4 "\n"}' cj.txt
This is a cj
Name Mark
zhaosan 87.12
lisi 90.123
wangwu 89.1233322
[root@localhost ~]# awk 'END {printf "The END \n"} {printf $2 "\t" $4 "\n"}' cj.txt
Name Mark
zhaosan 87.12
lisi 90.123
wangwu 89.1233322
The END
(2)关系运算符
> 大于
< 小于
>= 大于等于
<= 小于等于
== 等于。用于判断两个值是否相等,如果是变量赋值请使用“=”号
!= 不等于
~ 判断字符串A中是否包含能匹配B表达式的字符串
!~ 判断字符串A中 是否不包含能匹配B表达式的字符串
例如:
[root@localhost ~]# cat cj.txt | grep -v Name | awk '$4 >= 89 {printf $2 "\n"}'
lisi
wangwu
#加入了条件之后,只有条件成立动作才会执行,如果条件不满足,则动作不运行。虽然awk是列提取命令,但是也要按行来读入的。
[root@localhost ~]# awk '$2~ /lisi/ {printf $4 "\n"}' cj.txt
90.123
#先匹配第2列为lisi的行,再输出此行的第4列。
#在awk中使用//包含的字符串,awk命令才会查找。也就是说字符串必须使用//包含, awk命令才能正确识别。
3.内置变量
$0 代表目前awk所读入的整行数据。我们已知awk是一行一行读入数据的,$0就代表当前读入行的整行数据。
$n 代表目前读入行的第n个字段。
NF 当前行拥有的字段(列)总数。
NR 当前awk所处理的行,是总数据的第几行。
FS 用户定义分隔符。awk的默认分隔符是空格。如果想要使用其他分隔符需要FS 变量定义。
例:
cat /etc/passwd | grep "/bin/bash" | awk '{FS=":"} {printf $1 "\t" $3 "\n"}'
root:x:0:0:root:/root:/bin/bash
#这里“:”生效了。但是并没有把第一列和第三列截取出来,继续用BEGIN命令试试
cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN{FS=":"} {printf $1 "\t" $3 "\n"}'
root 0
#成功截取第一和第三字段的内容
cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "\t" $3"\t" NR "\t"NF"\n"}'
root 0 1 7
#分隔符是":"输出第一字段和第三字段 输出行号(NR)字段数(NF)如果只想查看sshd这个伪用户的相关信息需要:
cat /etc/passwd | awk 'BEGIN {FS=":"} $1=="sshd" {printf $1 "\t" $3 "\t" NR "\t" NF "\n"}'
sshd 74 32 7
#可以看到sshd伪用户的UID是74,是/etc/passwd文件的第32行,共有7个字段
4.流程控制
[root@localhost ~]# cat /root/cj.txt
ID Name gender Mark
1 zhaosan M 87.12
2 lisi M 90.123
3 wangwu M 89.1233322
#统计本次成绩的总分
[root@localhost ~]# awk 'NR==2{cj1=$4}
> NR==3{cj2=$4}
> NR==4{cj3=$4;totle=cj1+cj2+cj3;print "totle cj is" totle}' cj.txt
totle cj is266.366 #实现流程控制,假设如果成绩大于90,就是goodboy:
[root@localhost ~]# awk '{if (NR>=2) {if ($4>=90) print $2 " is a good boy \n"}}' cj.txt
lisi is a good boy
5.调用脚本
[root@localhost ~]# cat pass.awk
BEGIN {FS=":"}
{print$1"\t"$3}
[root@localhost ~]# awk -f pass.awk /etc/passwd #用-f选项来调用这个脚本。
root 0
bin 1
daemon 2
#此脚本可以用于/etc/passwd、/etc/shadow、/etc/group等以:为分隔符文件的查看。