Linux基础篇--文本处理工具

Linux基础篇–文本处理工具

本章内容概要
* 各种文本工具来查看、分析、统计文本
* grep命令用法
* 正则表达式
* 扩展正则表达式

6.1 文本工具

6.1.1 抽取文本的工具
  • 文件内容:less和cat
  • 文件截取:head和tail
  • 按列抽取:cut
  • 按关键字抽取:grep

文件查看
* 文件查看命令
  cat,tac,rev
* cat [OPTION]… [FILE]…
  -E:显示行结束符$
  -n:对显示出的每一行进行编号
  -A:显示所有控制符
  -b:非空行编号
  -s:压缩连续的空行成一行
* tac 反向显示文件内容(上下方向)
* rev 反向显示文件内容(左右方向)

[root@centos7 ~]#cat -E f1
aa$
bb$
cc$
[root@centos7 ~]#cat -n f1
     1  aa
     2  bb
     3  cc
[root@centos7 ~]#cat -A f3
aa$
bb  c$
cc$
$
dd$
$
[root@centos7 ~]#cat -b f3
     1  aa
     2  bb  c
     3  cc

     4  dd
[root@centos7 ~]#cat f1
aa
bb
cc
[root@centos7 ~]#tac f1
cc
bb
aa

[root@centos7 ~]#cat f2
aa  bb  cc
[root@centos7 ~]#rev f2
cc  bb  aa

分页查看文件内容
* more:分页查看文件
用法:more [OPTIONS…] FILE…
  -d: 显示翻页及退出提示
注意:more查看文件,到文件内容底部以后会自动退出
* less:一页一页地查看文件或STDIN输出
查看时有用的命令包括:
 /文本搜索  文本
 n/n 跳到下一个或上一个匹配
less 该命令是man命令使用的分页器

显示文本前或后行内容
* head [OPTION]… [FILE]…
  -c #: 指定获取前#字节
  -n #: 指定获取前#行
  -#: 指定行数
* tail [OPTION]… [FILE]…
  -c #: 指定获取后#字节
  -n #: 指定获取后#行
  -#:
  -f: 跟踪显示文件fd新追加的内容,常用日志监控。但是文件在其他窗口被删除,不会有提示
   相当于 –follow=descriptor
  -F: 跟踪文件名,相当于—follow=name –retry。文件在其他窗口被删除,会出现提示

知识扩展:
cat /dev/urandom | tr -dc '[:alnum:]' | head -c10 取前10位除了字母和数字的随机数作为密码

tr命令
注:由于该命令可以与本章多个命令相结合,因此在此回顾一下tr命令相关内容
* 转换和删除字符
* 语法:tr [OPTION]… SET1 [SET2]
* 选项:
 -c –C –complement:取字符集的补集
 -d –delete:删除所有属于第一字符集的字符
 -s –squeeze-repeats:把连续重复的字符以单独一个字符表示
 -t –truncate-set1:将第一个字符集对应字符转化为第二字符集对应的字符

[root@centos7 ~]#tr 'a-z' 'A-Z'
aaabbbccc123
AAABBBCCC123
[root@centos7 ~]#tr -d "[0-9]"
123vqadsa3241
vqadsa
[root@centos7 data]#echo {a..z} >f1
[root@centos7 data]#cat f1
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@centos7 data]#tr -d [f-m]  
a b c d e         n o p q r s t u v w x y z

按列抽取文本cut和合并文件paste
* cut [OPTION]… [FILE]…
  -d DELIMITER: 指明分隔符,默认tab
  -f FILEDS:
   #: 第#个字段
   #,#[,#]:离散的多个字段,例如1,3,6
   #-#:连续的多个字段, 例如1-6
  混合使用:1-3,7
  -c 按字符切割
  –output-delimiter=STRING指定输出分隔符

[root@centos7 ~]#cat /etc/passwd | cut -d: -f1,3,7
root:0:/bin/bash
bin:1:/sbin/nologin
daemon:2:/sbin/nologin
adm:3:/sbin/nologin
lp:4:/sbin/nologin
sync:5:/bin/sync
shutdown:6:/sbin/shutdown
halt:7:/sbin/halt
mail:8:/sbin/nologin
operator:11:/sbin/nologin
games:12:/sbin/nologin
[root@centos7 ~]#cat /etc/passwd | cut -c3-5
ot:
n:x
emo
m:x
:x:
nc:
utd
lt:
il:

cut和paste
* 显示文件或STDIN数据的指定列
 cut -d: -f1 /etc/passwd  按:号切割,并取出第7列
 cat /etc/passwd | cut -d: -f7
cut -c2-5 /usr/share/dict/words  取出整个文件第2到第5个字符
* paste合并两个文件同行号的列到一列
用法:paste [OPTION]… [FILE]…
  -d 分隔符:指定分隔符,两个文件中间以指定分隔符分隔开,默认用TAB
  -s : 所有行合成一行显示
  paste f1 f2 文件(横向)合到一块
  paste -s f1 f2 所有行合成一行

[root@centos7 ~]#paste f1 f2
aa  aa  
bb  bb  
vv  cc
dd  dd
xx  ee
[root@centos7 ~]#cat f1
aa
bb
vv
dd
xx
[root@centos7 ~]#cat f2
aa  
bb  
cc
dd
ee
[root@centos7 ~]#paste f1 f2
aa  aa  
bb  bb  
vv  cc
dd  dd
xx  ee
[root@centos7 ~]#paste -d: f1 f2
aa:aa  
bb:bb  
vv:cc
dd:dd
xx:ee
[root@centos7 ~]#paste -s f1 f2
aa  bb  vv  dd  xx
aa      bb      cc  dd  ee
6.1.2 分析文本的工具
  • 文本数据统计:wc
  • 整理文本:sort
  • 比较文本:diff和patch

收集文本统计数据wc
* wc命令统计的内容分别是:单词总数、行总数、字节总数和字符总数
* 可以对文件或STDIN的数据运行
如:wc /etc/passwd
 45  88  2311 /etc/passwd
 行数 字数 字节数
注意:当文本中出现汉字时,一个汉字占3个字符,加上换行符,会多出4个字符(字符和字节不是同一概念)
* 常用选项
 -l:只计数行数
 -w:只计数单词总数
 -c:只计数字节总数
 -m:只计数字符总数
 -L:显示文件中最长行的长度

[root@centos7 ~]#cat /etc/passwd |wc -l
45
[root@centos7 ~]#cat /etc/passwd |wc -w
88
[root@centos7 ~]#cat /etc/passwd |wc -c
2311
[root@centos7 ~]#cat /etc/passwd |wc -m
2311
[root@centos7 ~]#cat /etc/passwd |wc -L
99

文本排序sort
* 把整理过的文本显示在STDIN,不改变原始文件
用法:sort [options] file(s)
* 常用选项:
-r:执行反方向(由上至下)整理
-R:机排序
-n:执行按数字大小整理
-f:选项忽略(fold)字符串中的字符大小写
-u:选项(独特,unique)删除输出中的重复行
-t c:选项使用c做为字段界定符
-k X:选项按照使用c字符分隔的X列来整理能够使用多次
cat /etc/passwd |sort -t: -k3 -nr 取第3列uid进行从大到小排序

知识扩展:
seq 75 |sort -R |head -n 随机从75个数中取出一个数字,数字75可自定义

uniq
* uniq命令:从输入中删除前后相接的重复的行
* uniq [OPTION]… [FILE]…
  -c: 显示每行重复出现的次数
  -d: 仅显示重复过的行
  -u: 仅显示不曾重复的行
 注:连续且完全相同方为重复
* 常和sort命令配合使用:
 sort userlist.txt | uniq -c 去重并排序

知识扩展:
cat file1 file2 |sort |uniq -d 取两个文件的交集(重复的行)

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

diff foo.conf foo2.conf  
5c5  
< use_widgets = no  
\-\-\-  
\> use_widgets = yes  

 * 注明第5行有区别(改变)

赋值对文件改变patch
* diff 命令的输出被保存在一种叫做“补丁(diff.log)”的文件中
 * 使用-u选项来输出“统一的”diff格式文件,最适用于补丁文件
* patch 赋值在其他文件中践行的改变(谨慎使用)
 * 使用-b选项来自动备份改变了的文件
$ diff -u foo.conf foo2.conf > foo.patch
$ patch -b foo.conf foo.patch
示例:
diff -u f1 f2 >diff.log 把比较结果重定向到diff.log文件中
patch 根据“补丁”文件(diff.log)还原源文件(f2)
rm -rf f1 删除f1文件
patch -b f1 diff.log 根据diff.log文件恢复f1文件
先备份f1文件并将该文件重命名为f1.orig
然后根据diff.log恢复f2文件,但f2文件恢复后被重命名为f1
因此恢复后,f1文件即为f2文件内容,f1.orig文件为f1文件内容

练习:
1、找出ifconfig “网卡名” 命令结果中本机的IPv4地址
ifconfig ens33|head -n2 |tail -n1|tr -s " "|cut -d" " -f3
2、查出分区空间使用率的最大百分比值
df |tr -s " " %|cut -d% -f5|sort -nr|head -n1
3、查出用户UID最大值的用户名、UID及shell类型
cat /etc/passwd |cut -d: -f1,3,7|sort -t: -k2 -nr|head -n1
4、查出/tmp的权限,以数字方式显示
stat /tmp |head -n4 |tail -n1|tr -dc [:digit:]|cut -c1-4
5、统计当前连接本机的每个远程主机IP的连接数,并按从大到小排序
netstat -nt|tr -s " " : |cut -d: -f6|tr -dc "[:digit:].\n"|sort|uniq -c|sort -nr

6.2 Linux文本处理三剑客

  • grep:文本过滤工具
      grep(基本正则表达式),egrep(扩展正则表达式),fgrep(不知正则表达式搜索)
  • sed:stream editor,文本编辑工具
  • awk:Linux上的实现gawk,文本报告生成器
6.2.1 grep
  • grep: Global search REgular expression and Print out the line
     作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行
     模式:由正则表达式字符及文本字符所编写的过滤条件
  • 用法:
    grep [OPTIONS] PATTERN [FILE…]
      grep root /etc/passwd
      grep “$USER” /etc/passwd
      grep ‘$USER’ /etc/passwd
      grep `whoami` /etc/passwd
  • 选项:
     –color=auto: 对匹配到的文本着色显示
     -v: 显示不被pattern匹配到的行,取反
     -i: 忽略字符大小写
     -n:显示匹配的行号
     -c: 统计匹配的行数
     -o: 仅显示匹配到的字符串,字符会一个字符占用一行显示,排成一列
     -q: 静默模式,不输出任何信息,用于设置密码
     -A #: after, 后#行
     -B #: before, 前#行
     -C #:context, 前后各#行
     -e:实现多个选项间的逻辑或关系
      如:grep -e test1 -e test2 file 搜索既属于test1用户又属于test2用户的文件
     -w:匹配整个单词
     -E:使用ERE,相当于扩展正则表达式
     -F:相当于fgrep,不支持正则表达式

知识扩展:
查找1到100中包含9的数字
seq 100 |grep 9 |wc -l

6.3 正则表达式

  • REGEXP:由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能
  • 程序支持:grep,sed,awk,vim, less,nginx,varnish等
  • 分两类:
      基本正则表达式:BRE
      扩展正则表达式:ERE
        grep -E, egrep
  • 正则表达式引擎:
      采用不同算法,检查处理正则表达式的软件模块
      PCRE(Perl Compatible Regular Expressions)
    *元字符分类:字符匹配、匹配次数、位置锚定、分组
  • man 7 regex    man帮助第七章节
6.3.1 基本正则表达式元字符
  • 字符匹配
      . 匹配任意单个字符
      [] 匹配指定范围内的任意单个字符
      [^] 匹配指定范围外的任意单个字符
      [:alnum:] 字母和数字
      [:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
      [:lower:] 小写字母 [:upper:] 大写字母
      [:blank:] 空白字符(空格和制表符)
      [:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
      [:cntrl:] 不可打印的控制字符(退格、删除、警铃…)
      [:digit:] 十进制数字 [:xdigit:]十六进制数字
      [:graph:] 可打印的非空白字符
      [:print:] 可打印字符
      [:punct:] 标点符号
  • 匹配次数:用在要指定次数的字符后面,用于指定前面的字符要出现的次数
      * 匹配前面的字符任意次,包括0次
        贪婪模式:尽可能长的匹配
      .* 任意长度的任意字符
      \? 匹配其前面的字符0或1次
      + 匹配其前面的字符至少1次
      {n} 匹配前面的字符n次
      {m,n} 匹配前面的字符至少m次,至多n次
      {,n} 匹配前面的字符至多n次
      {n,} 匹配前面的字符至少n次
  • 位置锚定
      ^ 行首锚定,用于模式的最左侧
      $ 行尾锚定,用于模式的最右侧
      ^PATTERN$ 用于模式匹配整行
        ^$ 空行
        ^[[:space:]]*$ 空白行
      \< 或 \b 词首锚定,用于单词模式的左侧
      \> 或 \b 词尾锚定;用于单词模式的右侧

练习:
1、获取分区利用率,并从大到小排序
df |grep "^/dev/sd" |tr -s " " % |cut -d% -f5 |sort -nr
df |grep "dev/sd"|egrep -o "[0-9]{1,3}%"|egrep -o "[0-9]{1,3}" |sort -nr
2、统计/etc目录下所有以.conf结尾的文件的个数
ls -R /etc |grep "\.conf$"|wc -l
3、统计.rpm前的类似x86_64出现多少次
ls /misc/cd/Packages/*.rpm |rev |cut -d. -f2 |rev|sort|uniq -c
ls /misc/cd/Packages/ |grep -o "[^.]\+\.rpm"|cut -d. -f1|sort|uniq -c

  • 分组::() 将一个或多个字符捆绑在一起,当作一个整体进行处理,如:(root)+
  • 分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, …
  • \1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符
    示例: (string1+(string2)*)
      \1 :string1+(string2)*
      \2 :string2
  • 后向引用:引用前面的分组括号中的模式所匹配字符,而非模式本身
  • 或者:|
    示例1:a|b: a或b C|cat: C或cat (C|c)at:Cat或cat
    示例2:(1)root后面又出现root
    echo rootxxxxroot |grep "\(root\).*\1"
    结果为:rootxxxxroot
    (2)root和wang在后面分别又出现,root和wang之间有其他字符
    echo root233wangxxxxrootxxxwang |grep "\(root\).*\(wang\).*\1.*\2"
    结果为:root233wangxxxxrootxxxwang
    示例:在/etc/passwd文件中,前面出现root,后面又出现root的行,root不一定在行首
    grep "\(\\).*\1" /etc/passwd 使用首尾锚定
    结果显示为:root:x:0:0:root:/root:/bin/bash

注意:\1匹配的结果是前面的模式匹配的结果,而不是模式本身
示例:
[root@centos7 ~]#echo "aa roo xx ryy" |grep "\<\(r..\).*\1"
[root@centos7 ~]#
模式“\<\(r..\)”匹配的结果是roo,那么后面\1匹配的必须是roo,ryy不符合该结果

练习:
1、显示/proc/meminfo文件中以大小s开头的行(要求:使用两种方法)
grep -e "^s" -e "^S" /proc/meminfo
grep -i "^s" /proc/meminfo
2、显示/etc/passwd文件中不以/bin/bash结尾的行
grep -v "/bin/bash$" /etc/passwd
3、显示用户rpc默认的shell程序
cat /etc/passwd |grep "^rpc\>" |cut -d: -f7
4、找出/etc/passwd中的两位或三位数
grep -o "\<[0-9]\{2,3\}\>" /etc/passwd
5、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面有非空白字符的行
grep "^[[:space:]]\+\.*[^[:space:]]\+" /etc/grub2.cfg
6、找出“netstat -tan”命令结果中以LISTEN后跟任意多个空白字符结尾的行
netstat -tan |grep "\[[:space:]]\+"
7、显示CentOS7上所有系统用户的用户名和UID
cat /etc/passwd |cut -d: -f1,3
8、利用df和grep,取出磁盘各分区利用率,并从大到小排序
df |grep "/dev/sd"|grep -o "[0-9]\{1,3\}%"|grep -o "[0-9]\{1,3\}"|sort -nr

egrep及扩展的正则表达式
* egrep=grep -E
* egrep [OPTIONS] PATTERN [FILE…]
* 扩展正则表达式的元字符:
* 字符匹配:
  . 任意单个字符
  [] 指定范围的字符
  [^] 不在指定范围的字符

6.4 扩展正则表达式

  • 次数匹配:
      *:匹配前面字符任意次
      ?: 0或1次
      +:1次或多次
      {m}:匹配m次
      {m,n}:至少m,至多n次
  • 位置锚定:
      ^ :行首
      $ :行尾
      \<, \b :语首
      >, \b :语尾
  • 分组:
      ()
      后向引用:\1,\2,…
  • 或者:
      a|b: a或b
      C|cat: C或cat
      (C|c)at:Cat或cat

练习:
1、显示三个用户root、mage、wang的UID和默认shell
grep -E "(root|test1|yuan)" /etc/passwd |cut -d: -f3,7
2、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行
grep "^.*\>[^[:space:]]*()" /etc/rc.d/init.d/functions
3、使用egrep取出/etc/rc.d/init.d/functions中其基名
echo /etc/rc.d/init.d/functions |egrep -o "[^/]+$"
4、使用egrep取出上面路径的目录名
echo /etc/rc.d/init.d/functions |egrep -o "^.*/"
5、统计last命令中以root登录的每个主机IP地址登录次数
last |grep -w "root" |egrep -o "([0-9]{1,3}\.){3}[1-9]{1,3}"|sort|uniq -c|sort -nr
6、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255
ifconfig |egrep -o "(([0-9][1-9]?|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9][1-9]?|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
7、显示ifconfig命令结果中所有IPv4地址
ifconfig|egrep -o "([0-9]{1,3}\.){3}[1-9]{1,3}"
8、将此字符串:welcome to magedu linux 中的每个字符去重并排序,重复次数多的排到前面
echo "welcome to magedu linux" |grep -o "[[:alpha:]]" |sort|uniq -c|sort -nr

知识扩展:
获取IP地址:
1、使用cut命令:
centos7版本:
ifconfig ens33 | head -n2 |tail -n1|tr -s " " |cut -d " " -f3
centos6版本:
ifconfig eth0 | head -n2 |tail -n1 |tr -s " " : |cut -d : -f4
2、使用grep命令:
ifconfig ens33 |grep -w "inet"|tr -s " " :|cut -d: -f3
3、使用正则表达式(字符匹配):
ifconfig ens33 |grep -o '[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}'
以一个ip地址中的一位作为一个整体(如192. ,是三位加上.)
4、使用正则表达式(匹配次数):
方法1:ifconfig ens33 |grep -w "inet" |grep -o "[0-9.]\{7,\}" |head -n1 以一个ip地址作为一个整体(如1.1.1.1,是7位字符)
方法2:ifconfig ens33 |grep -o "inet [0-9.]\+"|cut -d" " -f2
5、使用正则表达式(分组):
ifconfig ens33 |grep -w "inet" |grep -o "\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}"|head -n1
6、使用扩展正则表达式:
ifconfig ens33 |grep -w "inet" |grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}"|head -n1

获取版本号:
cat /etc/centos-release |tr -dc '[:digit:].' | cut -d. -f1
cat /etc/redhat-release |tr -dc '[:digit:].' | cut -d. -f1

你可能感兴趣的:(Linux基础篇--文本处理工具)