Linux 三剑客 -- awk sed grep

吃可爱长大的小学妹 提交于 2019-12-30 18:51:30

本文由本人收集整理自互联网供自己与网友参考,参考文章均已列出,如有侵权,请告知!

顶配awk,中配sed,标配grep

awk 参考

sed 参考

grep 参考

在线查看linux命令速记表
appropos , history
two long didn't read

整理

我们都知道,在Linux中一切皆文件,比如配置文件,日志文件,启动文件等等。如果我们相对这些文件进行一些编辑查询等操作时,我们可能会想到一些vi,vim,cat,more等命令。但是这些命令效率不高,这就好比一块空地准备搭建房子,请了10个师傅拿着铁锹挖地基,花了一个月的时间才挖完,而另外一块空地则请了个挖土机,三下五除二就搞定了,这就是效率。而在linux中的“挖土机”有三种型号:顶配awk,中配sed,标配grep。使用这些工具,我们能够在达到同样效果的前提下节省大量的重复性工作,提高效率。

接下来我们就看一下sed的详细说明

sed 是Stream Editor(字符流编辑器)的缩写,简称流编辑器。什么是流?大家可以想象以下流水线,sed就像一个车间一样,文件中的每行字符都是原料,运到sed车间,然后经过一系列的加工处理,最后从流水线下来就变成货物了。
[root@master ~]# dirname  /etc/rc.d/init.d/functions 
/etc/rc.d/init.d
[root@master ~]# basename  /etc/rc.d/init.d/functions 
functions
grep -xf a.txt b.txt  //查询a与b共同存在的行
grep -vxf b.txt a.txt //查询a的行不在b文件中面的,就是a比b多出来的行


注意 \< 与 ^ \> 与$ 的区别, 一个 是行首行尾,一个是行内定锚
grep '\<g.*d\>' test

sed -rn 's/(.*)\.$/\1!/gp' test
记住 sed 为整行匹配, grep 只是查找匹配

grep -Ev '^#|^$' test

sed -r '/^#|^$/d' test


替换日期的斜杠
echo 2016/08/01| sed 's#/#:#g'

打印某个文件的奇偶行
sed -n '1~2p' test2.txt 
sed -n '2~2p' test2.txt

删除某个文件中的全部数字
cat test2.txt | tr -d '0-9'

sed 's/[0-9]//g' test2.txt
基名
[root@master ~]# echo /etc/sysconfig/network-scrips/ifconfig-eth0 | egrep -Eo '[^/]+$'
ifconfig-eth0
路径名
[root@master ~]# echo /etc/sysconfig/network-scrips/ifconfig-eth0 | egrep -Eo '^/.*/'
/etc/sysconfig/network-scrips/

cut -c 指定 区间  2,3,4   , 2- , -5 
echo abcdefgh | cut -c 2-4

显示/etc目录下,所有.conf结尾,且以m,n,r,p开头的文件或目录
ls -r /etc/ | grep  '^[mnrp].*.conf$'

ls -d /etc/[mnrp]*.conf

#显示/etc目录下所有以m开头以非数字结尾的文件或目录

ls -r /etc  | grep "^m.*[^[:digit:]]$"
ls -d /etc/m*[^[:digit:]]

找出 /proc/meminfo 文件中 以 大写或小写S 开头的行
grep "^[sS].*" /proc/meminfo 
sed -n "/^[sS].*/p" /proc/meminfo


找出 /etc/rc.d/init.d/functions 下 任意单词后面带有小括号
grep -E  "[[:alpha:]]*\(\)"  /etc/rc.d/init.d/functions

#去除文件空行
grep -v '^$' test.txt 

去掉注释
sed -i  "/^#.*$/d" test2.txt

# 查找第 三行第二列
#准备数据
vim person.txt

101,chensiqi,CEO
102,zhangyang,CTO
106,dandan, CS $PATH
103,Alex,COO
104,yy,CFO
105,feixue,CIO

# 方法 一 awk: 
awk -F "," 'BEGIN{printf("start...\n")} {if(NR==3){printf("%s",$2)}} END{printf("\n end...")}' person.txt

start...
dandan
 end...

# 简化版 awk:
awk -F "," 'NR==3{print $2}' person.txt 

# 方法二 sed :
sed -n '3p' person.txt  | cut -d "," -f "2"

#简化版 sed,其实 借助于  非特定行 3  则  delete  参数 !d
sed '3!d' person.txt | cut -d "," -f 2

# 方法三 grep:
cat -n person.txt | grep -E '^([[:space:]])(\1)*3'| cut -d "," -f "2"


# 提取 IP 地址
[root@master ~]# ifconfig eno16777736
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.32.129  netmask 255.255.255.0  broadcast 192.168.32.255
        inet6 fe80::20c:29ff:feb9:fd3f  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:b9:fd:3f  txqueuelen 1000  (Ethernet)
        RX packets 115663  bytes 23701583 (22.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 49651  bytes 30612378 (29.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


ifconfig |grep -Eo '(\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\>\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-5])'

ifconfig eno16777736 | sed -n '2p' | sed 's/.*inet//' | grep -E '[[:digit:]]+(\.[0-9]{1,3}){1,3}' -o

ifconfig  eno16777736 | sed -r -n '2s/.*inet(.*)netmask.*/\1/p'

ifconfig  eno16777736 | sed -n '2p' | sed -r 's/.*inet(.*)netmask(.*)/\1\2/'

[root@master ~]# cat /etc/centos-release
CentOS Linux release 7.1.1503 (Core) 
[root@master ~]# cat /etc/centos-release | sed -r -n 's/.*release[[:space:]]([[:digit:]]+).*/\1/p'


# 类似于 主外键关联, a.txt 中 第二列与 b.txt 第一列相等的 数据 查出来 一行输出

[root@master ~]# cat a.txt
张三|000001
李四|000002
[root@master ~]# cat b.txt
000001|10
000001|20
000002|30
000002|15


awk -F "|" 'NR==FNR{a[$2]=$0;next}{print a[$1]"|"$2}' a.txt b.txt

# 将文本文件的n和n+1行合并为一行,n为奇数行
sed 'N;s/\n//' a.txt



grep -C 2 '^[_[:alpha:]+]'  /etc/rc.d/init.d/functions



给定一个文件 file.txt,转置它的内容。

你可以假设每行列数相同,并且每个字段由 ' ' 分隔.

示例:

假设 file.txt 文件内容如下:

name age
alice 21
ryan 30
应当输出:

name alice ryan
age 21 30

[root@master ~]# awk '{for(i=1;i<=NF;i++){if(NR==1){arr[i]=$i} else { arr[i] = arr[i] " " $i }}} END{for(i=1;i<=NF;i++){print arr[i]}}'  file.txt
me alice ryan
age 21 30
[root@master ~]# cat file.txt
me age
alice 21
ryan 30


#统计下面test2.txt 文件中正常的数字部分 1|2...|7 每个数字出现的次数
[root@master ~]# cat test2.txt
     1  1|2|3|4|5|6|7
     2  1|2|3|4|5|6|7
     3  1|2|3|4|5|6|7
     4  1|2|3|4|5|6|7
    21  dfsd12342fsdf
    22  doctor23ljljsdf
    23  124234doctor
    24  Dasdfl2354534
    25  D434fasdfljo
    26
man#jldfjlasdfjas;df

sed  '21,27d' test2.txt | sed -r 's/[[:space:]]+[[:digit:]]+[[:space:]](.*)/\1/gp' |sed -rn 's/([[:digit:]])\|/\1\n/gp'|sort -rn|uniq -c|awk -F " " '{print $2,$1}'

小结:
    sort 预设分隔符为tab键所以是 -t
    sort -t :

    cut -d 代表分隔符
    cut  -d :

    awk -F 代表分隔符

显示/proc/meminfo文件中以大小s开头的行;(要求:使用两种方式)
sed -n '/^[sS]/p' /proc/meminfo 
grep '^[sS]'
grep -i '^s' /proc/meminfo

显示/etc/passwd文件中不以/bin/bash结尾的行
grep -v '/bin/bash$' /etc/passwd

找出/etc/passwd中的两位或三位数
grep -o  '\<[[:digit:]]\{2,3\}\>' /etc/passwd

显示/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面存非空白字符的行
grep '^[[:space:]].*[^[:space:]].*' /etc/grub2.cfg 

找出"netstat -tan"命令的结果中以‘LISTEN‘后跟0、1或多个空白字符结尾的行
netstat -tan | grep 'LISTEN\>[[:space:]]*$'

添加用户bash、testbash、basher以及nologin(其shell为/sbin/nologin),而后找出/etc/passwd文件中用户名同shell名的行
grep '^\(\<[[alnum]]\>\)+.*/\1$' /etc/passwd

显示当前系统root、mage或wang用户的UID和默认shell
grep -E '^root|^wang|^mage' /etc/passwd

找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行
grep   -E "^[[:alpha:]_]+\("    /etc/rc.d/init.d/functions 

统计以root身份登录的每个远程主机IP地址的登录次数
who | grep root |cut -d\( -f2|cut -d\) -f1|uniq -c

[root@master ~]# echo 15|awk '{x=8;for(i=1;i<$0;i++){for(j=1;j<=3*($0-i)-(x>0?x:0);j++)printf" ";for(k=i;k>=1;k--)printf"%d ",k;for(l=2;l<=i;l++)printf"%d ",l;printf"\n";x--};\
> for(i=1;i<=$0;i++){for(j=1;j<=(i<=$0-10+1?3*(i-1):3*(i-1)+2-(i-$0%10-10*int(($0-10)/10)));j++)printf" ";for(k=$0-i+1;k>=1;k--)printf"%d ",k;for(l=2;l<=$0-i+1;l++)printf"%d ",l;printf"\n"}}'                                  1 
                                2 1 2 
                              3 2 1 2 3 
                            4 3 2 1 2 3 4 
                          5 4 3 2 1 2 3 4 5 
                        6 5 4 3 2 1 2 3 4 5 6 
                      7 6 5 4 3 2 1 2 3 4 5 6 7 
                    8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 
                  9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 
               10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 
            11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 
         12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 
      13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 
   14 13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
   14 13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 
      13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 
         12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 
            11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 
               10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 
                  9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 
                    8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 
                      7 6 5 4 3 2 1 2 3 4 5 6 7 
                        6 5 4 3 2 1 2 3 4 5 6 
                          5 4 3 2 1 2 3 4 5 
                            4 3 2 1 2 3 4 
                              3 2 1 2 3 
                                2 1 2 
                                  1 


[root@master ~]# awk 'BEGIN {for(i=1;i<=4;i++) {for(j=1;j<=10-i;j++) {printf " ";}for(j=1;j<=(2*i-1);j++) {printf "*";}printf "\n";}}'
         *
        ***
       *****
      *******

awk 'BEGIN{for(i=1;i<=9;i++){ for(j=1;j<=i;j++){printf i"*"j"="i*j"\t"} print }}'

扩展

vim


df -h
Filesystem Size Used Avail Use% Mounted on
/dev/xvda 24G 13G 9.9G 55% /
tmpfs 501M 108K 501M 1% /dev/shm
top #动态查看进程消耗资源(cpu、内存)
top -H #查看各个线程资源消耗情况
free -m # 查看内存、swap使用情况,top也可以看

$ tar czf linuxeye.tar.gz ./linuxeye #tar打包压缩
$ tar xzf linuxeye.tar.gz #解压
zip & unzip #加-q参数不会显示压缩过程
$ zip -r linuxeye.zip ./linuxeye #zip压缩
$ unzip -q linuxeye.zip #安静的zip解压

前言:

    在服务器中对日志进行处理是十分常见的工作,所以运维对于各种文本工具来查看、分析、统计,是必备的基本工。那么学习正则表达式、grep、egrep、和tr、sort、uniq等常见的文件处理命令就十分有必要了。



1、工具分类

    文件内容:less和 cat

    文件截取:head和tail

    按列抽取:cut
    按关键字抽取:grep



2、工具集锦



2.1、文件内容查看命令:cat, tac,rev;



(1)cat



语法:

1
    cat [OPTION]... [FILE]...

选项:

1
2
3
4
5
-E: 显示行结束符$;
-n: 对显示出的每一行进行编号;
-A:显示所有控制符;
-b: 非空行编号;
-s:压缩连续的空行成一行;


(2)tac:行反向查看;



(3)rev:列反向查看;







2.2、分页查看文件内容:more、less


(1)more: 分页查看文件;



语法:

1
    more [OPTIONS...] FILE...

选项:

1
-d: 显示翻页及退出提示;



(2)less:一页一页地查看文件或STDIN输出;


1
2
3
4
查看时有用的命令包括:
    /文本: 搜索文本;
    ?文本: 搜索文本;
    n/N:跳到同向下一个 或 同向上一个匹配
注:less命令是man命令使用的分页器





2.3、显示文本前或后行内容:head、tail、tailf


(1)head



语法:

1
    head [OPTION]... [FILE]...
选项:

1
2
3
-c #: 指定获取前#字节
-n #: 指定获取前#行
-#: 指定行数


(2)tail 



语法:

1
    tail [OPTION]... [FILE]...
选项:

1
2
3
4
5
    -c #: 指定获取后#字节    
    -n #: 指定获取后#行
    -#:查看后几行;
    -f: 跟踪显示文件fd新追加的内容,常用日志监控;相当于 --follow=descriptor。
    -F: 跟踪文件名,相当于—follow=name --retry
(3)tailf

    类似tail –f,当文件不增长时并不访问文件;







2.4、按列抽取文本cut


语法:

1
 cut [OPTION]... [FILE]...


选项:

1
2
3
4
5
6
7
8
9
10
11
    -d DELIMITER: 指明分隔符,默认tab    
    -f FILEDS:
     
       FILEDS
       #: 第#个字段;
       #,#[,#]:离散的多个字段,例如1,3,6;
       #-#:连续的多个字段, 例如1-6;
       混合使用:1-3,7;
        
    -c 按字符切割;
    --output-delimiter=STRING指定输出分隔符;





示例:显示文件或STDIN数据的指定列;

1
2
3
4
5
6
7
8
    cut -d: -f1 /etc/passwd    
    cat /etc/passwd | cut -d: -f7
    cut -c2-5 /usr/share/dict/words
     
    [root@Centos6x ~]#cut -d: -f1,3 /etc/passwd
    root:0
    bin:1
    daemon:2


2.5、合并文件paste



paste:合并两个文件同行号的列到一行


语法:

1
    paste [OPTION]... [FILE]...

选项:

1
2
-d 分隔符:指定分隔符,默认用TAB
-s : 所有行合成一行显示


示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
    paste f1 f2    
    paste -s f1 f2
     
    [root@Centos6x ~]#paste f1 f2
        1
    a   2
    s   3
    a   4
    a   5
    s   6
    b
    c
    d


2.6、文本数据统计: wc



作用:

1
2
 收集文本统计数据,包括计数单词总数、行总数、字节总数和字符总数。
   可以对文件或STDIN中的数据统计。


示例:

1
2
3
    # wc story.txt    
    39   237    1901     story.txt
    行数 单词数 字节数

常用选项:

1
2
3
4
5
 -l 只计数行数;
 -w 只计数单词总数;
 -c 只计数字节总数;
 -m 只计数字符总数;
 -L 显示文件中最长行的长度;




2.7、整理文本: sort


1
实现文本排序;把整理过的文本显示在STDOUT,不改变原始文件。
语法:

1
    sort [options] file(s)

常用选项:

1
2
3
4
5
6
 -r 执行反方向(由上至下)整理;
 -n 执行按数字大小整理;
 -f 选项忽略( fold)字符串中的字符大小写;
 -u 选项(独特, unique)删除输出中的重复行;
 -t c 选项使用c做为字段界定符;
 -k X 选项按照使用c字符分隔的X列来整理;能够使用多次;


2.8、唯一性处理:uniq



1
从输入中删除前后相接的重复的行。




语法:

1
 uniq [OPTION]... [FILE]...




选项:

1
2
3
-c: 显示每行重复出现的次数;
-d: 仅显示重复过的行;
-u: 仅显示不曾重复的行;连续且完全相同方为重复;




1
2
uniq命令常和sort 命令一起配合使用:
    sort userlist.txt | uniq -c




2.9、比较文件: diff



比较两个文件之间的区别:

1
2
3
4
5
6
    diff foo.conf foo2.conf    
     
    5c5
    < use_widgets = no
    ---
    > use_widgets = yes    / 注明第5行有区别(改变)/



 diff:命令的输出被保存在一种叫做“补丁”的文件中;
 使用 -u 选项来输出“统一的( unified)” diff格式文件,最适用于补丁文件。


2.10、patch



patch:复制在其它文件中进行的改变(要谨慎使用)。


选项:

1
-b 选项来自动备份改变了的文件


示例:

1
2
$ diff -u foo.conf foo2.conf > foo.patch;
$ patch -b foo.conf foo.patch    /使用之前先备份foo.conf文件/;




3、文本三剑客——grep命令



Linux文本处理三剑客:grep、sed、awk;

1
2
3
   grep:文本过滤(模式: pattern)工具;grep, egrep, fgrep(不支持正则表达式搜索)。
 sed: stream editor,文本编辑工具。
 awk: Linux上的实现gawk,文本报告生成器。




grep: Global search REgular expression and Print out the line。


作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行。


模式(PATTERN):由正则表达式元字符及文本字符所编写的过滤条件。



语法:

1
grep [OPTIONS] PATTERN [FILE...]
示例:

1
2
3
4
grep root /etc/passwd
grep "$USER" /etc/passwd
grep '$USER' /etc/passwd
grep `whoami` /etc/passwd




命令选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    --color=auto: 对匹配到的文本着色显示。
    -v: 显示不被pattern匹配到的行。
    -i: 忽略字符大小写。
    -n: 显示匹配的行号。
    -c: 统计匹配的行数。
    -o: 仅显示匹配到的字符串。
    -q: 静默模式,不输出任何信息。
     
    -A #: after, 后#行。
    -B #: before, 前#行。
    -C #: context, 前后各#行。
     
    -e:实现多个选项间的逻辑or关系。
        grep –e ‘cat ’ -e ‘dog’ file
    -w:匹配整个单词。
    -E:使用ERE,支持扩展的正则表达式。。
    -F:相当于fgrep,不支持正则表达式。


4、正则表达式(REGEX)



REGEXP:由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能。
程序支持: grep,sed,awk,vim, less,nginx,varnish等



正则表达式分类:

1
2
    基本正则表达式: BRE;
    扩展正则表达式: ERE;


正则表达式引擎:

1
2
    采用不同算法,检查处理正则表达式的软件模块;
    PCRE( Perl Compatible Regular Expressions)


1
元字符分类:字符匹配、匹配次数、位置锚定、分组;
1
正则表达式man帮助获取:man 7 regex




4.1、基本正则表达式元字符



4.1.1、字符匹配



1
2
3
4
5
6
7
8
9
10
11
12
13
.  匹配任意单个字符
[] 匹配指定范围内的任意单个字符
[^] 匹配指定范围外的任意单个字符
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母 [:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字 [:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号


4.1.2、匹配次数





匹配次数:用在要指定次数的字符后面,用于指定前面的字符要出现的次数。



1
2
3
4
5
6
7
8
* 匹配前面的字符任意次,包括0次。贪婪模式,尽可能长的匹配。
.* 任意长度的任意字符
\? 匹配其前面的字符0或1次
\+ 匹配其前面的字符至少1次
\{n\} 匹配前面的字符n次
\{m,n\} 匹配前面的字符至少m次,至多n次
\{,n\} 匹配前面的字符至多n次
\{n,\} 匹配前面的字符至少n次


4.1.3、位置锚定



位置锚定:定位出现的位置。



1
2
3
4
5
6
7
8
^ 行首锚定,用于模式的最左侧
$ 行尾锚定,用于模式的最右侧
^PATTERN$ 用于模式匹配整行
^$ 空行
^[[:space:]]*$ 空白行
\< 或 \b 词首锚定,用于单词模式的左侧
\> 或 \b 词尾锚定;用于单词模式的右侧
\<PATTERN\> 匹配整个单词


4.1.4、分组及后向引用



分组: \(\) 将一个或多个字符捆绑在一起,当作一个整体进行处理,如: \(root\)\+


分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, ...。
\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符;


 示例:

1
2
3
    \(string1\+\(string2\)*\)
    \1 : string1\+\(string2\)*
    \2 : string2

后向引用:引用前面的分组括号中的模式所匹配字符, 而非模式本身




或者: \|

1
示例: a\|b: a或b C\|cat: C或cat \(C\|c\)at:Cat或cat






5、egrep及扩展的正则表达式


egrep = grep -E


语法:

1
    egrep [OPTIONS] PATTERN [FILE...]

扩展正则表达式的元字符:


字符匹配:

1
2
3
    . 任意单个字符    
    [] 指定范围的字符
    [^] 不在指定范围的字符



次数匹配:

1
2
3
4
    *:匹配前面字符任意次    
    ?: 0或1次+: 1次或多次
    {m}:匹配m次
    {m,n}:至少m,至多n次


位置锚定:

1
2
3
4
    ^ :行首    
    $ :行尾
    \<, \b :语首
    \>, \b :语尾




分组及后向引用:

1
2
    ():    
    后向引用: \1, \2, ...

或者:|

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