Linux中的文本处理工具

1、Linux上的文本处理三剑客

(1)grep,egrep,fgrep:文本过滤(通过模式pattern过滤)工具;
1)grep:默认用基本正则表达式过滤,但有选项-E,-F,-E用于扩展正则表达式;-F表示不支持正则表达式。
2)egrep:默认用扩展正则表达式过滤, 但有选项-G,-F,-G用于基本正则表达式,-F表示不支持正则表达式。
3)fgrep:默认不支持正则表达式,但有选项-E, -G,-E用于扩展正则表达式,-G用于基本正则表达式。
(2)sed:stream editor,流编辑器,是一种文本编辑工具;
(3)awk:Linux上的实现为gawk,文本报告生成器(格式化文本报告);

2、正则表达式

正则表达式(Regual Expression, REGEXP)由一类特殊字符及文本字符所编写的模式,其中有些字符不表示其字面意义,而是用于表示控制或通配的功能。正则表达式分为两类:基本正则表达式(BRE)和扩展正则表达式(ERE)。

3、grep

grep:Global search REgular expression and Print out the line.
作用:文本搜索工具,根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查,并打印匹配到的行。
模式:由正则表达式的元字符及文本字符所编写出的过滤条件。

grep  [OPTIONS]  PATTERN  [FILE...]
grep  [OPTIONS]  [-e PATTERN | -f FILE]  [FILE...]

-e        可以指定多个PATTERN
-f FILE   将多个PATTERN放在FILE中,从FILE中读取PATTERN

OPTIONS:
--color=auto:对匹配到的文本着色后高亮显示;
-i:ignorecase,忽略字符的大小写;
-o:仅显示匹配到的字符串本身;
-v, --invert-match:显示不能被模式匹配到的行;
-E:支持使用扩展的正则表达式元字符;
-q, --quiet, --silent:静默模式,即不输出任何信息;
-A #:after, 匹配到的后#行;
-B #:before,匹配到的前#行;
-C #:context,匹配到的前后各#行;

注意:CentOS6与CentOS7的区别:CentOS7上通过定义了grep的别名来高亮显示匹配到的字符串,CentOS6没有高亮显示。
(1)基本正则表达式
1)字符匹配:
. :匹配任意单个字符;
[]:匹配指定范围内的任意单个字符;
[^]:匹配指定范围外的任意单个字符;
[:digit:]、[:lower:]、[:upper:]、[:alpha:]、[:alnum:]、[:punct:]、[:space:]
                                                   字母     字母+数字 标点符号

[root@localhost ~]# grep "r[[:alpha:]][[:alpha:]]t" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

2)匹配次数:用在要指定其出现的次数的字符的后面,用于限制其前面字符出现的次数,默认工作于贪婪模式。
** : 匹配其前面的字符任意次;0,1,多次。
. * :匹配任意长度的任意字符。
?:匹配其前面的字符0次或1次;即其前面的字符是可有可无的。
+:匹配其前面的字符1次或多次;即其前面的字符要出现至少1次。
{m}:匹配其前面的字符m次;
{m,n}:匹配其前面的字符至少m次,至多n次;
{0,n}:至多n次;
{m,}:至少m次;
3)位置锚定:
^:行首锚定;用于模式的最左侧;
$ :行尾锚定;用于模式的最右侧;
^PATTERN$ :用于PATTERN来匹配整行;
^$ :空行,连空白字符都不包含;
^ [[:space:]]*$:空行或包含空白字符的行;
单词:非特殊字符组成的连续字符(字符串)都称为单词;
< 或 \b:词首锚定,用于单词模式的左侧;
> 或 \b:词尾锚定,用于单词模式的右侧;
<PATTERN>:匹配完整单词,精确锚定单词;

例:
1、显示/etc/passwd文件中不以/bin/bash结尾的行;
~]# grep -v "/bin/bash$" /etc/passwd						
2、找出/etc/passwd文件中的两位数或三位数;
~]# grep  "\<[0-9]\{2,3\}\>"  /etc/passwd    基本正则表达式
~]# grep -E "\<[0-9]{2,3}\>" /etc/passwd     扩展正则表达式  						
3、找出/etc/rc.d/rc.sysinit(CentOS6上)或/etc/grub2.cfg(CentOS7上)文件中,以至少一个空白字符开头,且后面非空白字符的行;
~]# grep  "^[[:space:]]\+[^[:space:]]"  /etc/grub2.cfg     基本正则表达式
~]# grep  "^[[:space:]]+[^[:space:]]"  /etc/grub2.cfg      扩展正则表达式						
4、找出"netstat -tan"命令的结果中以'LISTEN'后跟0、1或多个空白字符结尾的行;
~]# netstat -tan | grep  "LISTEN[[:space:]]*$"

空白字符包含空格也包含tab,即[[:space:]]包含空格也包含tab;
4)分组及引用
():将一个或多个字符捆绑在一起,当作一个整体进行处理;
(xy)*ab

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

He loves his lover.
He likes his lover.
She likes her liker.
She loves her liker.
~]# grep "\(l..e\).*\1" lovers.txt
后向引用:引用前面的分组括号中的模式所匹配到的字符,而非模式本身。

4、egrep

支持扩展的正则表达式实现类似于grep文本过滤功能,相当于grep -E。

egrep [OPTIONS] PATTERN [FILE...]
选项:
-i, -o, -v, -q, -A, -B, -C
-G:支持基本正则表达式

(1)扩展正则表达式
1)字符匹配:
.:任意单个字符;
[]:指定范围内的任意单个字符;
[^]:指定范围外的任意单个字符;
2)次数匹配:
*:任意次,0,1或多次;
?:0次或1次,其前的字符是可有可无的;
+:其前字符至少1次;
{m}:其前的字符m次;
{m,n}:至少m次,至多n次;
{0,n}:至多n次;
{m,}:至少m次;
3)位置锚定
^:行首锚定;
$:行尾锚定;
<, \b:词首锚定;
>, \b:词尾锚定;
4)分组及引用:
():分组,用括号括起来表示要引用的内容,不需要转义。括号内的模式匹配到的字符会被记录于正则表达式引擎的内部变量中;
后向引用:\1, \2, …
或:
a|b:a或者b;
C|cat:C或cat
(c|C)at:cat或Cat;
5)扩展正则表达式的使用语法:
grep -E 'PATTERN' FILE...
egrep 'PATTERN' FILE...

例:
1、找出/proc/meminfo文件中,所有以大写或小写S开头的行;至少有三种实现方式;
~]# grep -i "^s" /proc/meminfo
~]# grep "^[sS]" /proc/meminfo
~]# grep -E "^(s|S)" /proc/meminfo
2、显示当前系统上root、centos或user1用户的相关信息;
~]# grep -E "^(root|centos|user1)\>" /etc/passwd      行首,词尾锚定
3、找出/etc/rc.d/init.d/functions文件中某单词后面跟一个小括号的行;
~]# grep  -E  -o  "[_[:alnum:]]+\(\)"  /etc/rc.d/init.d/functions    
如果需要匹配alnum不能匹配到的字符(如_),需要把其加在外部括号中;					
4、使用echo命令输出一绝对路径,使用egrep取出基名;
~]# echo /etc/sysconfig/ | grep  -E  -o  "[^/]+/?$"				
5、找出ifconfig命令结果中的1-255之间的数值;
~]# ifconfig | grep  -E  -o  "\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>"
6、添加用户bash, testbash, basher以及nologin(其shell为/sbin/nologin);而后找出/etc/passwd文件中用户名同shell名的行;
~]# grep  -E  "^([^:]+\>).*\1$"  /etc/passwd

5、fgrep

fgrep不支持正则表达式元字符,给出的字符当作字符本身搜索,当无需用到元字符去编写模式时,使用fgrep必能更好。

6、wc

wc代表word count,是一种字数统计工具。

wc  [OPTION]...  [FILE]...
-l: lines,统计行数;
-w:words,统计单词个数;
-c: bytes,统计字符个数;
[root@localhost ~]# wc /etc/fstab
[root@localhost ~]# wc -l /etc/fstab
[root@localhost ~]# wc -w /etc/fstab
[root@localhost ~]# wc -c /etc/fstab

7、cut

cut是一种文本截取工具。
注意:原内容或原文件不受影响。

cut OPTION... [FILE]...
OPTION:
-d CHAR:以指定的字符为分隔符;
-f FIELDS:挑选出的字段;仅保留哪些字段;
#:指定的单个字段;
#-#:连续的多个字段;
#,#:离散的多个字段;
[root@localhost ~]# cut -d: -f1,3-5,7 /etc/passwd
[root@localhost ~]# wc -l /etc/rc.d/init.d/functions | cut -f1
605
[root@localhost ~]# wc -l /etc/rc.d/init.d/functions | cut -d' ' -f1
605

8、sort

sort  [OPTION]...  [FILE]...
-n:基于数值大小而非字符进行排序;
-t CHAR:指定分隔符;
-k #:用于排序比较的字段;
-r:逆序排序;
-f:忽略字符大小写
-u:uniq排序后去重,重复的行只保留一份;
重复行:连续且相同;
[root@localhost ~]# cut -d: -f3 /etc/passwd | sort        按字符排序
[root@localhost ~]# cut -d: -f3 /etc/passwd | sort -n     按数值排序
[root@localhost ~]# sort -t: -k3 -n /etc/passwd           以:为分隔,第3字段,按数值排序
[root@localhost ~]# cut -d: -f7 /etc/passwd | sort -u
/bin/bash
/bin/sync
/sbin/halt
/sbin/nologin
/sbin/shutdown
[root@localhost ~]# cut -d: -f7 /etc/passwd | sort -u | wc -l
5
[root@localhost ~]# grep "bash$" /etc/passwd | wc -l
2

9、uniq

uniq用于报告或移除重复的行,连续且重复的行仅保留一份。

uniq [OPTION]... [INPUT [OUTPUT]]
-c:显示每行的重复次数;
-u:仅显示未曾重复过的行;
-d:仅显示重复过的的行;
[root@localhost ~]# cut -d: -f7 /etc/passwd | sort | uniq -c
2 /bin/bash
1 /bin/sync
1 /sbin/halt
39 /sbin/nologin
1 /sbin/shutdown
[root@localhost ~]# cut -d: -f7 /etc/passwd | sort | uniq -u
/bin/sync
/sbin/halt
/sbin/shutdown
[root@localhost ~]# cut -d: -f7 /etc/passwd | sort | uniq -d
/bin/bash
/sbin/nologin

10、diff

diff用于逐行比较文件。

diff [OPTION]... FILES
diff  /PATH/TO/OLDFILE  /PATH/TO/NEWFILE > /PATH/TO/PATCH_FILE
-u:使用unfied机制,即显示要修改的行的上下文,默认为3行;

diff可以比较两个目录下的每一个文件,并对每一个文件生成一个单独的补丁,打补丁时,可以分别将补丁补到老目录下的每一个老文件中,使得老目录文件与新目录文件一模一样。

[root@localhost exercise]# diff -u fstab fstab.new
--- fstab	2016-11-28 09:57:45.874174879 +0800
+++ fstab.new	2016-11-28 09:50:57.180168482 +0800
@@ -2,7 +2,7 @@
#
# /etc/fstab
# Created by anaconda on Fri Nov 11 09:39:19 2016
-#
+# comment
 # Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#

11、patch

patch用于向文件打补丁。

patch [OPTIONS] -i /PATH/TO/PATCH_FILE /PATH/TO/OLDFILE    给老文件打补丁	
patch /PATH/TO/OLDFILE < /PATH/TO/PATCH_FILE		
patch -R -i  /PATH/TO/PATCH_FILE /PATH/TO/OLDFILE          给老文件去掉补丁
[root@localhost exercise]# cp /etc/fstab .
[root@localhost exercise]# ls
fstab
[root@localhost exercise]# cp fstab fstab.new
[root@localhost exercise]# nano fstab.new
[root@localhost exercise]# diff fstab fstab.new
5c5
< #
---
> # comment
[root@localhost exercise]# nano fstab.new
[root@localhost exercise]# diff fstab fstab.new > fstab.patch
[root@localhost exercise]# patch -i fstab.patch fstab
bash: patch: command not found...
[root@localhost exercise]# yum install patch
[root@localhost exercise]# patch -i fstab.patch fstab
patching file fstab
[root@localhost exercise]# cat fstab
[root@localhost exercise]# diff fstab fstab.new
[root@localhost exercise]# patch -R -i fstab.patch fstab
patching file fstab
[root@localhost exercise]# cat fstab

12、locate

locate用于在文件系统上查找符合条件的文件。
(1)locate的工作原理:
1)依赖于事先构建好的索引库;
2)系统自动实现(周期性任务);
3)手动更新数据库(updatedb);
4)索引库中存放的是文件路径,而不是文件本身。
(2)locate的工作特性:
1)查找速度快;
2)模糊查找;
3)非实时查找;
4)路径的任何位置出现都可以匹配。
(3)locate用法

locate  [OPTION]...  PATTERN...
-A, --all: 匹配符合多个PATTERN的文件名;
-b:只匹配路径中的基名,仍是模糊匹配;
-c:统计出共有多少个符合条件的文件;
-r:BRE,基于基本正则表达式来编写模式,不用-r,不可以使用正则表达式;

索引构建过程需要遍历整个根文件系统,极消耗资源。

13、find

locate是一种实时查找工具,通过遍历指定起始路径下文件系统的层级结构完成文件查找。
(1)find的工作特性
1)查找速度略慢;
2)精确查找;
3)实时查找。
(2)find用法

find [OPTIONS]  [查找起始路径]  [查找条件]  [处理动作]

查找起始路径:指定具体搜索目标起始路径;默认为当前目录;
查找条件:指定的查找标准,可以根据文件名、大小、类型、从属关系、权限等等标准进行,默认为找出指定路径下的所有文件;
处理动作:对符合查找条件的文件做出的操作,例如删除等操作,默认为输出至标准输出。
查找条件:表达式,包括选项和测试条件。测试条件的结果通常为布尔型(“true”, “false”)。
(3)查找方式
1)根据文件名查找:
-name “pattern” 支持使用globbing字符(* ,?,[],[^]);
-iname “pattern” 不区分文件名中字符的大小写,支持glob风格的通配符(*, ?, [], [^]),而不是正则表达式风格;
-regex pattern:基于正则表达式模式查找文件,匹配是整个路径,而非基名;

[root@localhost exercise]# find /etc -name "passwd"
/etc/passwd
/etc/pam.d/passwd

2)根据文件从属关系查找:
-user USERNAME:查找属主为指定用户的所有文件;
-group GRPNAME:查找属组为指定组的所有文件;
-uid UID:查找属主为指定的UID的所有文件,包含目录;
-gid GID:查找属组为指定的GID的所有文件,包含目录;
-nouser:查找没有属主的文件,属主用户已删;
-nogroup:查找没有属组的文件,属组已删;
3)根据文件的类型查找:
-type TYPE:
f: 普通文件
d: 目录文件
l:符号链接文件
b:块设备文件
c:字符设备文件
p:管道文件
s:套接字文件
符号链接文件的权限为777,其他用户也有写和执行权限,这是为了不影响目标文件的权限,实际生效权限由目标权限决定。

[root@localhost exercise]# find /dev -type b -ls        查找块设备文件,-ls是处理动作,即用ls -l列出每个文件的详细信息
9784    0 brw-rw----   1 root     disk       8,   6 Nov 29 15:38 /dev/sda6
9783    0 brw-rw----   1 root     disk       8,   5 Nov 29 15:38 /dev/sda5
9782    0 brw-rw----   1 root     disk       8,   4 Nov 29 15:38 /dev/sda4
9781    0 brw-rw----   1 root     disk       8,   3 Nov 29 15:38 /dev/sda3
9780    0 brw-rw----   1 root     disk       8,   2 Nov 29 15:38 /dev/sda2
9779    0 brw-rw----   1 root     disk       8,   1 Nov 29 15:38 /dev/sda1
9749    0 brw-rw----   1 root     disk       8,   0 Nov 29 15:38 /dev/sda
9744    0 brw-rw----   1 root     cdrom     11,   0 Nov 29 15:38 /dev/sr0
[root@localhost exercise]# find /dev -type l -ls    显示符号链接文件指到哪了(即符号链接文件的详细信息)

4)组合测试:
与:-a, 默认组合逻辑;
或:-o,符合二者其中之一即可;
非:-not, !,条件取反;

[root@localhost exercise]# find /tmp -nouser -type f -ls  显示/tmp下没有属主的普通文件的详细信息;
[root@localhost exercise]# find /tmp -nouser -a -type f -ls     也可以
[root@localhost exercise]# find /tmp -nouser -o -type f -ls
[root@localhost exercise]# find /tmp -not -type f -ls
例:
1、找出/tmp目录下属主为非root的所有文件;
[root@localhost exercise]# find /tmp -not -user root
2、找出/tmp目录下文件名中不包含fstab字符串的文件;
[root@localhost exercise]# find /tmp -not -name "*fstab*"
3、找出/tmp目录下属主为非root,而且文件名不包含fstab字符串的文件;
[root@localhost exercise]# find /tmp -not -user root -a -not -name "*fstab*"
[root@localhost exercise]# find /tmp -not \( -user root -o -name "*fstab*" \) -ls
注意:括号需要转义。

-not A -a -not B = -not (A -o B)
-not A -o -not B = -not (A -a B)
!A -a !B = !(A -o B)
!A -o !B = !(A -a B)
5)根据文件的大小查找:
-size [+|-]#UNIT
常用单位:k, M, G
默认单位:字节
#UNIT为使用ls -lh看到的文件大小,如文件为174k
#UNIT:(#-1, #],匹配范围:(173,174],173.1k符合
-#UNIT:[0,#-1],匹配范围:[0,173],173.1k不符合
+#UNIT:(#, oo),匹配范围:(174,oo),173.1k不符合,174.1k符合
6)根据时间戳查找:
以“天”为单位:
-atime [+|-]# 访问时间,例如,距现在3天,#为3
#:[#, #-1) 距现在3天(72小时)以前,不足四天(96小时)(72小时~96小时之间)
-#:(#, 0] 距现在72小时以内(0~72小时)
+#:(oo, #-1] 距现在四天以前(96小时以前)
-mtime 修改时间
-ctime 改变时间
以“分钟”为单位:
-amin
-mmin
-cmin

[root@localhost exercise]# find /etc +atime 7 -ls     查找/etc目录下访问时间在7天以前的文件
[root@localhost exercise]# stat /etc/tcsd.conf        查看文件时间戳

7)根据权限查找:
-perm [/|-]mode
mode:精确权限匹配;
/mode:任何一类用户(u,g,o)的权限中的任何一位(r,w,x)符合条件即满足;9位权限之间存在“或”关系;
-mode:每一类用户(u,g,o)的权限中的每一位(r,w,x)同时符合条件即满足;9位权限之间存在“与”关系;

[root@localhost exercise]# find ./ -perm 644 -ls
524295    4 -rw-r--r--   1 root     root          275 Nov 29 20:50 ./testshell.sh
524294    4 -rw-r--r--   1 root     root          693 Nov 28 22:17 ./fstab
524292    4 -rw-r--r--   1 root     root           24 Nov 28 09:52 ./fstab.patch
524291    4 -rw-r--r--   1 root     root          697 Nov 28 09:50 ./fstab.new
[root@localhost exercise]# find ./ -perm /222 -ls       查找至少有一类用户有写权限的文件
[root@localhost exercise]# find ./ -perm /111 -ls       查找至少有一类用户有执行权限的文件
[root@localhost exercise]# find ./ -perm /001 -ls       查找其他人有执行权限的文件,属主属组不关心
[root@localhost exercise]# find ./ -perm /002 -ls       查找其他人有写权限的文件,属主属组不关心
[root@localhost exercise]# find ./ -perm -222 -ls       查找所有用户都有写权限的文件
[root@localhost exercise]# find ./ -not -perm -222 -ls  查找至少有一类用户没有写权限

(4)处理动作
-print:输出至标准输出;默认的动作;
-ls:类似于对查找到的文件执行“ls -l”命令,输出文件的详细信息;
-delete:删除查找到的文件;
-fls /PATH/TO/SOMEFILE:把查找到的所有文件的长格式信息保存至指定文件中;
-ok COMMAND {} ; :对查找到的每个文件执行由COMMAND表示的命令;每次操作都由用户进行确认;{}用来引用找到的文件的文件名;
-exec COMMAND {} ; :对查找到的每个文件执行由COMMAND表示的命令,不再由用户确认;{}用来引用找到的文件的文件名。

[root@localhost exercise]# find ./ -nouser -a -nogroup -ok chown root:root {} \;
将没有属主属组的文件改为root属主和属组;
[root@localhost exercise]# find ./ -perm /002 -exec mv {} {}.danger \;
将其他人有写权限的文件后缀加上.danger,{}用来引用找到的文件的文件名,没改权限;

find传递查找到的文件路径至后面的命令时,是先查找出所有符合条件的文件路径,并一次性传递给后面的命令。但是有些命令不能接受过长的参数,此时命令执行会失败;另一种方式可规避此问题:

find | xargs COMMAND     由xargs调用后面的命令

(5)find例子

1、查找/var目录下属主为root,且属组为mail的所有文件或目录;
~]# find /var -user root -a -group mail -ls
2、查找/usr目录下不属于root, bin或hadoop的所有文件或目录;用两种方法;
~]# find /usr -not -user root -a -not -user bin -a -not -user hadoop
~]# find /usr -not \( -user root -o -user bin -o -user hadoop \) -ls				
3、查找/etc目录下最近一周内其内容修改过,且属主不是root用户也不是hadoop用户的文件或目录;
~]# find /etc -mtime -7 -a -not \( -user root -o -user hadoop \) -ls
~]# find /etc -mtime -7 -a -not -user root -a -not -user hadoop -ls					
4、查找当前系统上没有属主或属组,且最近一周内曾被访问过的文件或目录;
~]# find  /  \( -nouser -o -nogroup \)  -atime  -7  -ls
~]# find  /  -nouser -o -nogroup -ls    如果写为这样,则意为( -nouser ) -o ( -nogroup -ls )		
5、查找/etc目录下大于1M且类型为普通文件的所有文件;
~]# find /etc -size +1M -type f -exec ls -lh {} \;
6、查找/etc目录下所有用户都没有写权限的文件;
~]# find /etc -not -perm /222 -type f -ls					
7、查找/etc目录下至少有一类用户没有执行权限的文件;
~]# find /etc -not -perm -111 -type f -ls
8、查找/etc/init.d/目录下,所有用户都有执行权限,且其它用户有写权限的所有文件;
~]# find /etc -perm -113 -type f -ls

14、sed

sed [OPTION]… ‘script’ [input-file] …
地址定界编辑命令,sed脚本
常用选项:
-n:不输出模式空间中的内容至屏幕;
-e script, --expression=script:多点编辑;
-f /PATH/TO/SED_SCRIPT_FILE,每行一个编辑命令;
-r, --regexp-extended:支持使用扩展正则表达式;
-i[SUFFIX], --in-place[=SUFFIX]:直接编辑原文件 ;
~]# sed -e 's@^#[[:space:]]*@@' -e '/^UUID/d' /etc/fstab
(1)地址定界
1)空地址:对全文进行处理;
2)单地址:
#:指定行;
/pattern/:被此模式所匹配到的每一行;
3)地址范围:
#,#、#,+#、#,/pat1/、/pat1/,/pat2/、 $:最后一行;
4)步进:~
1~2:所有奇数行;
2~2:所有偶数行;
(2)编辑命令
d:删除;
p:显示模式空间中的内容;
a \text:在行后面追加文本“text”,支持使用\n实现多行追加;
i \text:在行前面插入文本“text”,支持使用\n实现多行插入;
c \text:把匹配到的行替换为此处指定的文本“text”;
w /PATH/TO/SOMEFILE:保存模式空间匹配到的行至指定的文件中;
r /PATH/FROM/SOMEFILE:读取指定文件的内容至当前文件被模式匹配到的行后面;文件合并;
=:为模式匹配到的行打印行号;
!:条件取反;地址定界!编辑命令;
s///:查找替换,其分隔符可自行指定,常用的有s@@@, s###等;
替换标记:
g:全局替换;
w /PATH/TO/SOMEFILE:将替换成功的结果保存至指定文件中;
p:显示替换成功的行;
(3)高级编辑命令
h:把模式空间中的内容覆盖至保持空间中;
H:把模式空间中的内容追加至保持空间中;
g:把保持空间中的内容覆盖至模式空间中;
G:把保持空间中的内容追加至模式空间中;
x:把模式空间中的内容与保持空间中的内容互换;
n:覆盖读取匹配到的行的下一行至模式空间中;
N:追加读取匹配到的行的下一行至模式空间中;
d:删除模式空间中的行;
D:删除多行模式空间中的所有行;
(4)例子

1. 删除/boot/grub/grub2.cfg文件中所有以空白字符开头的行的行首的所有空白字符;
~]# sed  's@^[[:space:]]\+@@' /etc/grub2.cfg
2. 删除/etc/fstab文件中所有以#开头的行的行首的#号及#后面的所有空白字符;
~]# sed  's@^#[[:space:]]*@@'  /etc/fstab
3. 输出一个绝对路径给sed命令,取出其目录,其行为类似于dirname;
~]# echo "/var/log/messages/" | sed 's@[^/]\+/\?$@@'
~]# echo "/var/log/messages" | sed -r 's@[^/]+/?$@@'

15、awk

(1)概述
文本处理三工具:grep, sed, awk
grep, egrep, fgrep:根据PATTERN的文本过滤工具。
sed:行编辑器,在模式空间和保持空间进行的行编辑工作。
awk:报告生成器,格式化文本输出。
AWK是Aho, Weinberger, Kernighan三人的姓名首字母缩写,New AWK缩写为NAWK,GNU awk缩写为gawk。
gawk是一种模式搜索和处理语言。
(2)基本用法:gawk [options] 'program' FILE ...
program:PATTERN{ACTION STATEMENTS},语句之间用分号分隔。
选项:
-F:指明输入时用到的字段分隔符;
-v var=value: 自定义变量;
(3)print
print item1, item2, ...
要点:
1)逗号分隔符;
2)输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式;
3)如省略item,相当于print $0。
(4)变量
1)内建变量
FS:input field seperator,默认为空白字符;
OFS:output field seperator,默认为空白字符;
RS:input record seperator,输入时的换行符;
ORS:output record seperator,输出时的换行符;
NF:number of field,字段数量:{print NF}, {print $NF};
NR:number of record, 行数;
FNR:各文件分别计数;行数;
FILENAME:当前文件名;
ARGC:命令行参数的个数;
ARGV:数组,保存的是命令行所给定的各参数;
2)自定义变量
1 -v var=value:变量名区分字符大小写;
2 在program中直接定义;
(5)printf命令
格式化输出:printf FORMAT, item1, item2, ...
1)FORMAT必须给出;
2)不会自动换行,需要显式给出换行控制符\n;
3)FORMAT中需要分别为后面的每个item指定一个格式化符号;
格式符:
%c:显示字符的ASCII码;
%d, %i:显示十进制整数;
%e, %E:科学计数法数值显示;
%f:显示为浮点数;
%g, %G:以科学计数法或浮点形式显示数值;
%s:显示字符串;
%u:无符号整数;
%%:显示%自身;
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;
%3.1f
-:左对齐;
+:显示数值的符号;
(6)操作符
1)算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x
+x: 转换为数值;
2)字符串操作符:没有符号的操作符,字符串连接;
3)赋值操作符:
=, +=, -=, *=, /=, %=, ^=, ++, –
4)比较操作符:
>, >=, <, <=, !=, ==
5)模式匹配符:
~:是否匹配;
!~:是否不匹配;
6)逻辑操作符:
&&, ||, !
(6)函数调用:function_name(argu1, argu2, ...)
(7)条件表达式:selector?if-true-expression:if-false-expression
# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
(8)PATTERN
1)empty:空模式,匹配每一行;
2)/regular expression/:仅处理能够被此处的模式匹配到的行;
3)relational expression:关系表达式,结果有“真”有“假”,结果为“真”才会被处理。真:结果为非0值,非空字符串。
4)line ranges:行范围,startline,endline:/pat1/,/pat2/
注意: 不支持直接给出数字的格式。
~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
5)BEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本之前执行一次;
END{}:仅在文本处理完成之后执行一次;
(9)常用的action
1)Expressions
2)Control statements:if, while等;
3)Compound statements:组合语句;
4)input statements
5)output statements
(10)控制语句
if(condition) {statments}
if(condition) {statments} else {statements}
while(conditon) {statments}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
delete array[index]
delete array
exit
{ statements }
1)if-else
语法:if(condition) statement [else statement]
使用场景:对awk取得的整行或某个字段做条件判断;
2)while循环
语法:while(condition) statement
条件“真”,进入循环,条件“假”,退出循环。
使用场景:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用;
3)do-while循环
语法:do statement while(condition)
意义:至少执行一次循环体;
4)for循环
语法:for(expr1;expr2;expr3) statement
特殊用法:能够遍历数组中的元素,语法:for(var in array) {for-body}
5)switch语句
语法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}
6)break和continue
break [n]
7)next
提前结束对本行的处理而直接进入下一行;
8)array
关联数组:array[index-expression]
index-expression:
1 可使用任意字符串;字符串要使用双引号;
2 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
若要判断数组中是否存在某元素,要使用"index in array"格式进行;
若要遍历数组中的每个元素,要使用for循环:for(var in array) {for-body}
注意:var会遍历array的每个索引;
state[“LISTEN”]++
state[“ESTABLISHED”]++
(11)函数
1)内置函数
数值处理:rand():返回0和1之间一个随机数;
字符串处理:
length([s]):返回指定字符串的长度;
sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;
split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;
2)自定义函数

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页