当前位置:首页 > 技术文章 > 正文内容

Centos7学习笔记(四)——grep、sed、awk

ivker_lee5年前 (2020-08-09)技术文章253

1、grep——print lines matching a pattern打印匹配内容的行(多行)

命令格式:grep [参数] 过滤匹配内容 [文件名]或者grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

常用参数:

-v 取反过滤 ◆◆

-i 忽略大小写  ◆◆(find 命令可以用-iname)

-n 对过滤后的内容,显示源文件行号  ◆◆

-w 按单词为单位过滤。◆◆

-o只输出匹配的内容。◆◆

-E使用扩展规则

-r递归查找

-l只显示文件名

-r例题:

在当前目录下找到所有.cc的文件中包含“host”字样的文件

find ./ -type f -name ".cc" |xargs grep "host"       #《=========常规写法

grep -r "host" ./    #《======grep写法

例题:新建num1.txt文件并在其中键入1-30数字序列,并显示数字10-20的行。

第一问:seq 30 >num1.txt

或 echo -e {1..30}"\n" >num1.txt

第二问:head -20 num1.txt|tail -11

或者grep 10 -B 20 num1.txt

或者grep 10 -A 10 num1.txt

或者grep 15 -C 5 num1.txt

例题:写出删除文件abc.txt中的空行(注意,有3种写法)(空格开头没内容的也算空行)

第一种写法:grep -v "^$" abc.txt               #《======初级

第二种写法:egrep -v "^$|^ +$" abc.txt         #《=====中级

第三种写法:egrep -v "^ *$" abc.txt             #《========高级

sed -nr '(^ *$)d'  abc.txt                #《=========sed的写法


2、sed——stream editor for filtering and transforming text过滤和转换文本的流编辑器

命令格式:sed [参数选项] [sed内置命令字符] [文件名]

常用参数:

-n 取消默认sed的输出,常与sed内置命令字符p连用

-i 直接修改文件内容,而不是输出到终端。可以用-i.bak的形式备份(在修改前)

-f 引用一个脚本文件内容到命令中执行

-r引用扩展正则

PS:(-i参数与其他参数同时用时,要放其他参数最后。否则会把其他参数,当成备份文件格式。另外,i和n不能同时用,否则造成清空其他行内容的效果。)


sed内置命令字符

s——替换sub-expressions,s是针对字符串处理。,g作为s替换的修饰符,还要其他,比如p,i,I等修饰符。

d——删除(delete)

a——在某一行后追加(增加)内容(append),用法:na(n是数字,代表具体行数)

i——在某一行前插入(增加)内容(insert),用法:ni(n是数字,代表具体行数)

c——替换某一行内容。c是针对行内容替换。

I——忽略正则匹配部分的大小写

q——立即退出当前sed程序,使其不再执行后面的命令,也不在读取后面的行。还有Q也是一样的作用,两者的区别在于,q在退出前还会自动输出模式空间(已读取到数据的内存空间)的内容,而Q不会输出。具体见后面例子

n——手动读取下一行


例题:1、输出文件的第2、3行(查)

image.png

2、查看参数-n的作用(查)

image.png

3、查看文件中含mail的行(查)

image.png

4、删除文件中含list单词的行(删)

image.png

5、替换文件中的root为study字串(改)

image.png

6、将文件中的ssh替换成ftp,mail替换成tftp(改)

image.png

这里,主要是用-e增加多项替换操作。(如果需要真实修改,需要增加-i)

7、将第一行内容替换为I test.

image.png

8、删除指定的行

image.png其实,这里可以用‘1d;4d;6d;8d’写法,不需要-e

[root@studylinux ~/test]#sed '1,5d' statetab    #《====  这里是删除第1到5行
#
# Examples: 
#
#   /root
#   /etc/ftp
#   /var/spool/tftp
#
这里还有一种情形,
m~n
表示从m行开始每隔n行就再取一行,也就是取行号满足m+(x*n)其中n>=0的行。因此,要取所有奇数行,应写为1~2,取所有偶数行,写为2~2。取从第4行开始,每隔3行的行,写为4~3。单取50行,写为50~0。

删除a.sh中包含"#"开头的注释行,但第一行的#!/bin/bash不删除。

sed '/^#/{1!d}' a.sh


9、在第2行后增加I test.和I study again.这样两行。

image.png

另一个例子:在第四行之后追加内容

image.png这里,最后一个\t后的\符号,可加可不加,但是,如果在\后直接回车执行了,那么效果完全不同

image.png

10.用sed取出stat /etc/hosts结果中的644(文件权限值)。

image.png

注意,这里的思路:1、要取644值,它在stat /etc/hosts输出结果的第4行。

2、取值并打印输出,对sed来说,必然是要用s###g,来匹配对应的内容,然后用p来打印。

3、因为这里必然是0-9之间的数字,并且重复3次,所以,用扩展正则的()取整体,然后用\1来反向替代。


[root@studylinux ~/test]#stat /etc/hosts|sed -nr 's#.*\(0(.*)/-.*$#\1#gp'  #《====通过stat文件的方式,取文件的整个权限值
664
[root@studylinux ~/test]#ip add |sed -nr 's#.*inet (.*)/.*brd.*$#\1#gp'    #《=====取ip add输出后的ip地址值
192.168.205.129
ifconfig |sed -nr '2s#^.*inet (.*) netm.*$#\1#gp'                #《=======取ifconfig输出后的IP地址值

11、搜索脚本a.sh,当搜索到使用了"."或"source"命令加载环境配置脚本时就输出并立即退出。

sed -n -r '/^[ \t]*(\.|source) /{p;q}' a.sh                 #《=====这里的q,就是在匹配成功后,立刻退出sed循环


12、搜索出httpd.conf中"DocumentRoot"开头的行的行号,允许有前导空白字符。

sed -n '/^[ \t]*DocumentRoot/{p;=}' httpd.conf                #《=======这里的=,是用来输出sed命令所处理的当前行行号。
                                                                        如果"="命令前没有"p"输出命令,且没有使用"-n"选项,则是输出在Document所在行的前一行,因为SCRIPT最后的自动输出动作也有输出流。

13、搜索a.txt中包含"redirect"字符串的行以及其下一行,并输出。

sed -n '/redirect/{p;n;p}' a.txt

再例如下面的命令。

echo -e "abc\ndef\nxyz" | sed '/abc/{n;=;p}' 
abc
2
def
def
xyz

从结果中可以分析出,"n"读取下一行前输出了"abc",然后立即读入了下一行,所以输出的行号是2而不是1,因为这时候行号计数器已经读取了下一行,随后命令"p"输出了该模式空间的内容,输出后还有一次自动输出的隐含动作,所以"def"被输出了两次。

14、删除a.sh中所有"#"开头(可以包括前导空白)的注释符号"#",但第一行"#!/bin/bash"不处理。

sed -i '2,$s/^[ \t]*#//' a.sh                 #《======这里,注意用的是“2,$”,在sed中,$表示它所处理的最后一行的行号。但是,不能用“$-1”这样的方式来表示倒数第二行的行号,为何?
                                                       因为sed只有在处理到最后一行时,才知道它是最后一行,然后在内存中才能赋值最后一行行号值给$,在此之前,$是没有值的,又怎么能$-1呢?

15、将a.sh中"cmd1 && cmd2 || cmd3"的cmd2和cmd3命令对调个位置。

sed 's%&&\(.*\) ||\(.*\)%\&\&\2 ||\1%' a.sh             #《=============这里使用了"%"代替"/",且在REPLACEMENT部分对"&"进行了转义,因为该符号在REPLACEMENT中时表示的是引用REGEXP所匹配的所有内容。

16、批量修改文件格式。

ls *.jpg

ls *.jpg|xargs -n1|sed -nr 's#(.*)jpg#mv \1jpg \1txt #gp'|bash

image.png

17、取反内容——取出/etc/ssh/sshd_config,不包括空行和注释行的内容。

sed -nr '/^$|^#/!p' /etc/ssh/sshd_config

image.png



3、awk——pattern scanning and processing language 样式(模式)扫描和处理语言

用法:awk  [option]  'pattern{action}' file ...

***重点:pattern,可以翻译做“条件”。一般用关系表达式来作为条件,比如

            x > 10 判断变量x是否大于10

            x  == y 判断变量x是否等于变量y

            A ~ B  判断字符串A中是否包含能匹配B表达式的子字符串

            A !~ B  判断字符串A中是否不包含能匹配B表达式的子字符串

具体的“条件”可以按下表分类:


条件类型条件说明
awk保留字
BEGIN在awk程序一开始时,尚未读取任何数据之前执行,BEGIN后的动作只在程序开始时执行一次
END在awk程序处理完所有数据,即将结束时执行,END后的动作只在程序结束时执行一次
关系运算符>大于
<
小于
>=大于等于
<=小于等于
!=不等于
==等于。判断两个值是否相等。
A~B
判断字符串A中是否包含能匹配B表达式的子字符串
A!~B判断字符串A中是否不包含能匹配B表达式的子字符串
正则表达式/正则/如果在“//”中可以写入字符,也可以写入正则表达式

以上条件或者判断,可以灵活使用,组合使用。甚至也可以结合awk的内置函数来做判断。以下是awk的内置函数:


awk内置变量
作用
$0代表awk当前所读入的整行数据,awk仍然是按行处理数据
$nn是数字,代表目前读入行的第n个字段
NF当前行拥有的字段总数
NR当前awk所处理的行,是总数据的第几行。
FS用户自定义分隔符。awk默认分隔符为空格,如果想用其他分隔符,就要用FS变量定义
ARGC命令行参数个数
ARGV命令行参数数组
FNR当前文件中的当前记录数(对输入文件起始为1)
OFMT数值的输出格式(默认为%.6g)
OFS输出字段的分隔符(默认为空格)
ORS输出记录的分隔符(默认为换行符)
RS
输入记录的分隔符(默认为换行符)

 这里需要注意的是:如果用FS来自定义分隔符,那么,需要尽量用BEGIN{FS=":"}的形式,不然容易出现第一行处理不了的情况

image.png

action,就是动作。可以是print或printf格式化输出。也可以是流程控制语句(if..else、for..do等)

awk中,'pattern{action}'可以跟多段,即awk [option] 'pattern{action}' 'pattern{action}' file这样的形式。



参数(opiton)

-F指定分隔符(可以是字符串、符号或者是正则表达式)

image.png

注意,这里有一个“action”——print,但没有pattern。

上图中,$1代表第一列,$2的话,代表第二列以此类推。但有特殊的:

$0   ——     代表了整行(或者说是一行的所有列)

$NF    ——   代表了最后一列

$(NF-1)    —— 倒数第二列,这里可以类推,如$(NF-3)


image.png

NR——已经读出的记录数,就是行号,从1开始

image.png

下例:筛选出有adm字符串的行

image.png

下例:删除带有root的行

image.png

image.png

4、printf

语法:printf '输出类型输出格式' 输出内容

参数:%ns——n是数字,指代输出几个字符。

%ni——n是数字,指代输出几个整数

%m.nf——m和n都是数字,指代输出的整数位和小数位。比如%8.2f,指总共输出8位,其中6位是整数,2位是小数。


\a——表示输出警告声音。

\b——表示输出退格键,也即是输出backspace键

\f——清除屏幕

\n——换行

\r——回车键,即Eneter键

\t——水平制表符,即tab键

\v——垂直制表符,即tab键


printf命令不能直接跟文件名,基本上,只用在awk命令中。

printf '%s\t%s\t%i\t%i\t%8.2f \n' $(cat test.txt)

(print和printf区别——print只能用于awk语句,区别在于print已经格式化好了,用\n去分隔行。printf不行,需要自行添加\n去分隔每一行)

5、字符串操作函数

gsub(r, s [, t])

r是被替换部分,s是替换后部分。具体看下图。注意每部分需要被//或者""起来

image.png

6、awk中变量的使用

image.png

变量名之前,不需要加$符号,如果加了$符号,基本都等同于$0。如图

image.png

如果需要申明一串字符为,必须给其加双引号"",否则字符串会被视为变量。(如上面gsub中,被替换后的内容,若为字符串,必须加双引号)


7、利用awk数组,统计/var/log/secure文件中,每个“Failed password”登录失败的IP。

image.png

awk '/Failed password/{count[$(NF-3)]++}END{for (IP in count) print count[IP],IP}' /var/log/secure

思路:先grep 'Failed password' /var/log/secure|head,确定输出内容的格式。

image.png

然后改用awk,确定需要输出的IP为$(NF-3)列。

image.png

再将整个$(NF-3)列放入一个count[]数组中,就可以参与运算了。


统计nginx的access.log日志中IP地址访问次数,并从高到低排序。

awk '{count[$1]++}END{for (IP in count) print count[IP],IP}' /var/log/nginx/access.log|sort -nrk1


以下是各类三剑客实例:


C6下ifconfig eth0,取IP地址值

ifconfig eth0|awk 'NR==2{print $2}'|awk -F ":" '{print $2}'     #《===== 笨办法
ifconfig eth0|awk -F "(addr:)|(Bcast)" 'NR==2{print $2}'  
ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'             #《======   这里,用了多分隔符,分别是用空格和:符号做分隔,由于inet前有很多空格,且addr也作为了一段,print的变$3了

ip add下,取IP地址值

ip add|awk 'NR==8{print $2}'|awk -F "/" '{print $1}'     #《===== 笨办法
ip add|awk -F "(inet )|(/)" 'NR==8{print $2}'
ip add|awk -F "[ /]+" 'NR==8{print $3}'       #《======   这里,用了多分隔符,分别是用空格和/符号做分隔,由于ip add前有很多空格,那么用2种分隔符后,print的变$3了

C7下,ifconfig eth0,取IP地址值

ifconfig eth0|awk 'NR==2{print $2}'
ifconfig eth0 |sed -nr 's#^.*inet (.*) netm.*$#\1#gp'

ip add下,取IP地址值

ip add|awk 'NR==9{print $2}'|awk -F "/" '{print $1}'   #《======= 笨办法
ip add|awk -F "(inet )|(/)" 'NR==9{print $2}'
ip add|awk -F "[ /]+" 'NR==9{print $3}'        #《======   这里,用了多分隔符,分别是用空格和/符号做分隔,由于ip add前有很多空格,那么用2种分隔符后,print的变$3了
ip add|sed -nr '9s#.*inet (.*)\/.*$#\1#gp'


1、显示/proc/meminfo文件中以大小s开头的行(要求:使用两种方法)
         i.  cat /proc/meminfo |grep -i "^s"
        ii.  cat /proc/meminfo |grep  "^\(s\|S\)"
2、显示/etc/passwd文件中不以/bin/bash结尾的行

          cat /etc/passwd |grep -v ":/bin/bash$"         

3、显示用户rpc默认的shell程序

          cat /etc/passwd |grep -w "^rpc" |cut -d: -f 7

         grep "rpc" /etc/passwd |awk -F ":" '{print $NF}'

4、找出/etc/passwd中的两位或三位数
          cat /etc/passwd |grep -wo "[[:digit:]]\{2,3\}"                      ##《====注意这里的grep参数w,必不可少,少了执行结果不同
5、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面有非空白字符的行
          cat /etc/grub2.cfg | grep "^[[:space:]]\+[^' '].*" 或   cat /etc/grub2.cfg | grep "^[[:space:]]\+[^[:space:]].*"
6、找出“netstat -tan”命令结果中以LISTEN后跟任意多个空白字符结尾的行
          netstat -tan | grep ".*LISTEN[[:space:]]*$"
7、显示CentOS7上所有系统用户的用户名和UID

         cat /etc/passwd |cut -d: -f1,3 |grep -w "[1-9][0-9]\{,2\}$"

image.png

8、添加用户bash、testbash、basher、sh、nologin(其shell为/sbin/nologin),找出/etc/passwd用户名和shell同名的行

         cat /etc/passwd |grep -w "^\([^:]*\):.*/\1$"

image.png

9、利用df和grep,取出磁盘各分区利用率,并从大到小排序

        df |grep "^/dev/sd"|grep -wo "[0-9]\+%"|sort -nr


10、显示三个用户root、mage、wang的UID和默认shell
         cat /etc/passwd |grep -w "^\(root\|mage\|wang\)" |cut -d: -f 3,7
11、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行
         cat /etc/rc.d/init.d/functions |grep -i "^\([_[:alnum:]]\+(\)"
12、使用egrep取出/etc/rc.d/init.d/functions中其基名
          echo "/etc/rc.d/init.d/functions" | grep -Eo "[^/]*[/]?$"|tr -d "/" 
13、使用egrep取出上面路径的目录名
          echo "/etc/rc.d/init.d/" | grep -Eo "..*[/]\<"                                  ###《====注意这里,grep用了"\<",表示匹配<符号后的内容,如果不加双引号,那么就是用\来转义<符号而已。下面14题例子也是同样用法。
14、统计last命令中以root登录的每个主机IP地址登录次数
        last |grep -w "^root.*\<pts" |  grep -wE "((([0-9])|([1-9][0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-9])|([1-9][0-9])|(1[0-9]{,2})|(2[0-4][0-9])|(25[0-5])){1}[[:space:]]" |tr -s " "|cut -d " " -f3|sort|uniq -c  
15、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255
           [0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
16、显示ifconfig命令结果中所有IPv4地址
          ifconfig |grep -owE "((([0-9]{1,2})|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-9]{1,2})|(1[0-9]{,2})|(2[0-4][0-9])|(25[0-5])){1}[[:space:]]"
17、将此字符串:welcome to  magedu linux 中的每个字符去重并排序,重复次数多的排到前面

              cat test | grep -o "[[:lower:]]"|sort |uniq -c|sort -nr |tr -s ' ' | cut -d " " -f 3 |tr -d '\n'

18、如何在系统添加“test1test2、...test30"这样的30个用户,并把它们密码都修改为”123456"

seq 30|sed -nr 's#(.*)#useradd test\1#gp'|bash

seq 30|sed -nr ‘s#(.*)#echo "123456"|passwd --stdin test\1#gp’|bash              #《=======两条命令的实现方式,太麻烦


echo test{1..30}|xargs -n1|sed -nr 's#(.*)#useradd \1;echo "123456"|passwd --stdin \1#gp' |bash                #《=========一条命令的实现方式


19、有以下文本文件chengji.txt


cat chengji.txt 
序号 姓名 成绩1 补考成绩1 成绩2 补考成绩2 成绩3 上机成绩 身高(cm)
1 曾庆虎 42 96 118 150 91 100 11
2 王昌斌 57 98 80 148.5 70 100 102
3 苏威鹏 86 100 92 148 79.5 100 170
4 王晓 68.5 100 104 149 84 100 123
5 刘明 54 100 139.5 77 92 100 184
6 苏旭波 82 95 60.5 147 85 100 102
7 郭伟 70 100 125 148 76.5 100 211
8 郭俊宁 88 100 145 99 80 100 0.9
9 张刚 43 100 74.5 150 76.5 100 21
10 贺子星 71 100 52.5 145 79 95 65

1)请将序号5人员的历次成绩取出,并按从高到低排序。

grep "^5" chengji.txt|xargs -n1|tail -7|head -6|sort -nr


20、假定系统/dev/sda3是根目录,取出根目录磁盘占有率的整数值。

df -h |grep "/dev/sda3"|awk -F "[ %]+" '{print $5}'

df -h|grep "/dev/sda3"|awk '{print $5}'|cut -d "%" -f 1




复习一点:

在a.txt文本中过滤xxx字符串,分别用grep、sed、awk的写法

grep "xxx" a.txt

sed -n '/xxx/p' a.txt

awk '/xxx/{print}' a.txt

问题2:删除字符串xxx

grep -v "xxx" a.txt

sed  '/xxx/d' a.txt

awk  '!/xxx/{print}' a.txt

问题3:将xxx替换为yyy

sed -n 's/xxx/yyy/gp' a.txt

awk '{gsub(/xxx/,"yyy");print $0}' a.txt                           #《=========这里,用了awk的内置函数gsub

awk提供了许多强大的字符串函数,见下表:
awk内置字符串函数
gsub(r,s)    在整个$0中用s替代r
gsub(r,s,t)    在整个t中用s替代r
index(s,t)    返回s中字符串t的第一位置
length(s)    返回s长度
match(s,r)    测试s是否包含匹配r的字符串
split(s,a,fs)    在fs上将s分成序列a
sprint(fmt,exp)    返回经fmt格式化后的exp
sub(r,s)    用$0中最左边最长的子串代替s
substr(s,p)    返回字符串s中从p开始的后缀部分
substr(s,p,n)    返回字符串s中从p开始长度为n的后缀部


    


分享给朋友:

相关文章

 Centos7学习笔记(十七)- iptable防火墙

Centos7学习笔记(十七)- iptable防火墙

本文大部分内容摘录自https://www.cnblogs.com/f-ck-need-u/p/7397146.html1、syn flood攻击查看在linux系统中,可以用以下命令查看是否遭受syn flood攻击。netstat -tnlpa | grep tcp | awk '{print $6}' | sort | uniq -c2、防火墙数...

正则表达式超全速查手册

正则表达式超全速查手册

一、校验数字的表达式数字:^[0-9]*$n位的数字:^\d{n}$至少n位的数字:^\d{n,}$m-n位的数字:^\d{m,n}$零和非零开头的数字:^(0|[1-9][0-9]*)$非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$有两位小数的正实数:^[0-9]+(.[0-9]{2})?$有1~3位小数的正实数:^...

 Centos7学习笔记(十八)- nginx基础与模块

Centos7学习笔记(十八)- nginx基础与模块

一、安装安装分为2种,yum安装和源码包编译安装。yum又分为官方源安装和epel源安装。官方的参考官方文档,主要执行以下3步:sudo yum install yum-utilssudo vi /etc/yum.repo.d/nginx.repo[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ g...

Centos7学习笔记(八)-基础命令(三)

Centos7学习笔记(八)-基础命令(三)

1、rsync作为一个同步(备份,增量备份)命令,它的选项非常的多,常用的组合是avz,当然,如果需要建立备份服务,那么-n必然是用的多的参数选项。关于rsync的用法详细说明,参考网上的这篇原文链接:https://www.cnblogs.com/f-ck-need-u/p/7220009.html#blog21,文章写的非常好,有大量的通俗易懂的例子及解释。以下关于rsync参数选项的说明,就抄录自该文章。v:显示rsync过程中详细信息。可以使用"-vvvv"获取更详细...

Centos7学习笔记(六)——shell编程初步

Centos7学习笔记(六)——shell编程初步

1、shell编程的一些基础a)shell编程有两类变量,                             全局变量(环境变量)——  一般指系统内置的变量,或者手动用export、declare等方式宣称,写入/etc/profile(~./bash_profile、~/bashrc、/etc/bashrc)的全局变量 ...

Centos7学习笔记(三)——重定向、通配符、正则

Centos7学习笔记(三)——重定向、通配符、正则

1、STDIN、STDOUT、STDERR输入重定向和输出重定向的符号和作用,分别在下面2个表中。注意:当输出结果是error时,是不能将结果重定向到“标准输出”中,反之,输出结果是“标准输出”,也不能重定向至错误输出中。如下图实例:[study@nfs01 ~]$sudo echo "00 1 * * * /usr/bin/rsync  -avz -r /etc/r...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。