欢迎光临
我们一直在努力

Linux正则+三剑客详解,日常文本处理效率翻倍

一、Linux 正则表达式

文章摘要: 本文全面介绍了 Linux 系统中正则表达式的基础知识及其在文本处理工具中的应用。主要内容包括:1)正则表达式的基本概念与分类(普通正则与扩展正则);2)字符集匹配规则(如 .、[…]、[^…]、转义符 \\ 等);3)定位符的使用(^、$、\\b、\\B 等);4)次数限定符(*、+、?、{n}、{m,n} 等);5)分组与反向引用。同时,文章详细讲解了 Linux 三剑客(grep、sed、awk)的使用方法,涵盖 grep 的多种选项与模式匹配、sed 的文本编辑与模式寻址、awk 的脚本结构与内置变量等核心功能,并通过大量实际命令示例演示了如何利用正则表达式进行高效的文本过滤、搜索与处理。

• 正则表达式作为一个 pattern,将 pattern 与要搜索的字符串进行匹配,以便查找一个或多个字符串。
• 正则表达式,自成体系,由普通字符(例如字符 a 到 z)和元字符组成的文字模式。
• 普通字符:没有显式指定为元字符的所有可打印和不可打印字符字符,包括所有大写和小写字母、所有数字、所有标点符号和其他一些符号。
• 元字符:出了普通字符之外的字符。
• 正则表达式,工具(vim、grep、less等)和程序语言(Perl、Python、C等)都使用正则表达式。
正则表达式分类:
• 普通正则表达式
• 扩展正则表示,支持更多的元字符。

1.环境准备

[root@client ~ 17:06:57]# cat > words <<EOF
> cat
> category
> acat
> concatenate
> cbt
> c1t
> cCt
> c-t
> c.t
> dog
> EOF

2.普通字符

[root@client ~ 17:07:16]# cat words | grep 'cat'
cat
category
acat
concatenate

3.字符集

(1).

匹配除换行符(\\n、\\r)之外的任何单个字符,相等于[^\\n\\r]。

[root@client ~ 17:07:25]# cat words | grep 'c.t'
cat
category
acat
concatenate
cbt
c1t
cCt
c-t
c.t

(2)[…]

匹配 […] 中的任意一个字符。

[root@client ~ 17:12:36]# cat words | grep 'c[ab]t'
cat
category
acat
concatenate
cbt

(3)[a-z] [A-Z] [0-9]
  • [a-z],匹配所有小写字母。
  • [A-Z],匹配所有大写字母。
  • [0-9],匹配所有数字。

[root@client ~ 17:12:45]# cat words | grep 'c[a-z]t'
cat
category
acat
concatenate
cbt

[root@client ~ 17:13:35]# cat words | grep 'c[A-Z]t'
cCt

[root@client ~ 17:13:42]# cat words | grep 'c[0-9]t'
c1t

[root@client ~ 17:13:51]# cat words | grep 'c[a-z0-9]t'
cat
category
acat
concatenate
cbt
c1t

[root@client ~ 17:14:00]# cat words | grep 'c[a-zA-Z0-9]t'
cat
category
acat
concatenate
cbt
c1t
cCt

# 要想匹配-符号,将改符号写在第一个位置
[root@client ~ 17:14:13]# cat words | grep 'c[-a-zA-Z0-9]t'
cat
category
acat
concatenate
cbt
c1t
cCt
c-t

(4)[^…]

匹配除了 […] 中字符的所有字符。

[root@client ~ 17:14:36]# cat words | grep 'c[^ab]t'
c1t
cCt
c-t
c.t

# ^放中间会被当做普通字符
[root@client ~ 17:17:35]# cat words | grep 'c[a^b]t'
cat
category
acat
concatenate
cbt

(5)\\

将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。
例如, ‘n’ 匹配字符 ‘n’。\\n 匹配换行符。序列 \\ 匹配 \\,而 ( 则匹配 (。

[root@client ~ 17:18:15]# cat words | grep 'c\\.t'
c.t

# 匹配普通字符,虽然可以匹配,但强烈建议不要在前面加\\
[root@client ~ 17:20:00]# cat words | grep 'c\\at'
cat
category
acat
concatenate

(6)|

| 符号是扩展表达式中元字符,指明两项之间的一个选择。要匹配 |,请使用 \\|。

# 使用egrep或者grep -E 匹配
[root@client ~ 18:24:33]# cat words | egrep 'cat|dog'
cat
category
acat
concatenate
dog
# 或者
[root@client ~ 18:26:07]# cat words | grep -E 'cat|dog'
cat
category
acat
concatenate
dog

(7)字符集总结
POSIX 字符类等价 ASCII 简写字符范围说明
[:digit:] [0-9] 十进制数字:0123456789
[:xdigit:] [0-9a-fA-F] 十六进制:09、AF、a~f
[:lower:] [a-z] 小写英文字母
[:upper:] [A-Z] 大写英文字母
[:alpha:] [A-Za-z] 大小写全部字母 = [:lower:]+[:upper:]
[:alnum:] [0-9A-Za-z] 字母 + 数字 = [:alpha:]+[:digit:]
[:blank:] [ \\t] 横向空白:空格、制表符 (\\t),不含换行
[:space:] [ \\t\\n\\r\\f\\v] 全空白:blank + 换行 \\n、回车 \\r、换页 \\f、垂直制表 \\v,[:blank:]⊂[:space:]
[:punct:] ASCII 标点 !"#$%&'()*+,-./:;<=>?@[]^_{ }~` 所有可见标点符号
[:graph:] 可见非空格 [:alnum:]+[:punct:],看得见、不含空格的字符
[:print:] 全部可打印 [:graph:] + 空格,所有能打印出来的字符(含空格)
[:cntrl:] 控制字符 ASCII:0~31 (八进制 000~037)、127 (DEL,八进制 177),不可打印控制码
(8)非打印字符

终端中不显示的字符,例如换行符。

字符描述
\\cx 匹配由x指明的控制字符。例如, \\cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符。
\\f 匹配一个换页符。等价于 \\x0c 和 \\cL。
\\n 匹配一个换行符。等价于 \\x0a 和 \\cJ。
\\r 匹配一个回车符。等价于 \\x0d 和 \\cM。
\\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \\f\\n\\r\\t\\v]。注意 Unicode 正则表达式会匹配全角空格符。
\\S 匹配任何非空白字符。等价于 [^ \\f\\n\\r\\t\\v]。
\\w 匹配字母、数字、下划线。等价于 [A-Za-z0-9_]
\\W 匹配任何非单词字符。等价于[^A-Za-z0-9_]
\\t 匹配一个制表符。等价于 \\x09 和 \\cI。
\\v 匹配一个垂直制表符。等价于 \\x0b 和 \\cK。

grep 命令支持\\w、\\W、\\s、\\S。

4.定位符

1.^

匹配行首位置。

[root@client ~ 18:26:15]# cat words | grep '^cat'
cat
category

2.$

匹配行末位置。

[root@client ~ 18:36:51]# cat words | grep 'cat$'
cat
acat

# 查看 /var/log/message Jun 1 17:01:0[1-9]时间段发生的事件
[root@client ~ 18:37:34]# cat /var/log/messages | head -n10
Jun 1 09:46:02 client rsyslogd: [origin software="rsyslogd" swVersion="8.24.0-57.el7_9.3" x-pid="980" x-info="http://www.rsyslog.com"] rsyslogd was HUPed
Jun 1 10:01:01 client systemd: Started Session 4 of user root.
Jun 1 11:01:01 client systemd: Started Session 5 of user root.
Jun 1 12:01:01 client systemd: Started Session 6 of user root.
Jun 1 13:01:01 client systemd: Started Session 7 of user root.
Jun 1 14:01:01 client systemd: Started Session 8 of user root.
Jun 1 15:01:01 client systemd: Started Session 9 of user root.
Jun 1 16:01:01 client systemd: Started Session 10 of user root.
Jun 1 17:01:01 client systemd: Started Session 11 of user root.
Jun 1 17:29:07 client kernel: e1000: ens33 NIC Link is Down

[root@client ~ 18:41:30]# cat /var/log/messages | egrep '^Jun 1 17:01:0[1-9]'
Jun 1 17:01:01 client systemd: Started Session 11 of user root.

# 只包含cat的行
[root@client ~ 18:41:46]# cat words | grep '^cat$'
cat

# 排除/etc/profile文件中以#开头的行
[root@client ~ 18:43:10]# cat /etc/profile | egrep '^[^#]'
pathmunge () {
case ":${PATH}:" in
*:"$1":*)
;;
......

# 查询/etc/profile文件中有效行
[root@client ~ 18:43:19]# cat /etc/profile | egrep -v '^#|^$'
pathmunge () {
case ":${PATH}:" in
*:"$1":*)
;;
*)
if [ "$2" = "after" ] ; then
......

# 查看系统中有哪些仓库
[root@client ~ 18:46:18]# yum install -y yum-utils
[root@client ~ 18:46:31]# yum-config-manager | grep '^\\[' | grep -v main
[base]
[epel]
[extras]
[updates]

3.\\b

匹配一个单词边界。

[root@client ~ 18:46:55]# echo hello cat kitty >> words
[root@client ~ 18:48:34]# cat words | grep '\\bcat'
cat
category
hello cat kitty
[root@client ~ 18:48:40]# cat words | grep 'cat\\b'
cat
acat
hello cat kitty
[root@client ~ 18:48:50]# cat words | grep '\\bcat\\b'
cat
hello cat kitty

4.\\B

非单词边界匹配。

[root@client ~ 18:48:57]# cat words | grep '\\Bcat\\B'
concatenate

5.\\< 和 \\>

•\\< ,匹配一个单词左边界。
• \\>,匹配一个单词右边界。

[root@client ~ 18:49:33]# cat words | grep '\\<cat'
cat
category
hello cat kitty
[root@client ~ 18:51:20]# cat words | grep 'cat\\>'
cat
acat
hello cat kitty

5.限定次数

1.*

匹配前面的子表达式任意次数。

[root@client ~ 18:51:27]# echo dg >> words
[root@client ~ 18:52:10]# echo doog >> words
[root@client ~ 18:52:16]# cat words | grep 'do*g'
dog
dg
doog

2.+

+是扩展表达式元字符,匹配前面的子表达式一次以上次数。

[root@client ~ 18:52:23]# cat words | egrep 'do+g'
dog
doog

3.?

? 是扩展表达式元字符,匹配前面的子表达式一次以下次数。

[root@client ~ 18:53:18]# cat words | egrep 'do?g'
dog
dg

4.{n}

{} 是扩展表达式元字符,用于匹配特定次数。例如:{n},配置n次。

[root@client ~ 18:53:54]# cat words | egrep 'do{2}g'
doog

5.{m,n}

{m,n},是扩展表达式元字符,用于匹配次数介于m-n之间。

[root@client ~ 18:54:29]# echo dooog >> words
[root@client ~ 18:55:05]# echo doooog >> words

[root@client ~ 18:55:15]# cat words | egrep 'do{2,3}g'
doog
dooog

6.{m,}

{m,},是扩展表达式元字符,匹配前面的子表达式m次以上次数。

[root@client ~ 18:55:21]# cat words | egrep 'do{2,}g'
doog
dooog
doooog

7.{,n}

{,n},是扩展表达式元字符,匹配前面的子表达式n次以下次数。

[root@client ~ 18:56:07]# cat words | egrep 'do{,3}g'
dog
dg
doog
dooog

8.()

标记一个子表达式。

[root@client ~ 18:56:42]# echo dogdog >> words
[root@client ~ 18:57:40]# echo dogdogdog >> words
[root@client ~ 18:57:46]# echo dogdogdogdog >> words

[root@client ~ 18:57:52]# cat words | egrep '(dog){2,3}'
dogdog
dogdogdog
dogdogdogdog

[root@client ~ 18:57:59]# cat words | egrep '(dog){2,}'
dogdog
dogdogdog
dogdogdogdog

9.综合案例

如何过滤出以下内容中所有有效IPv4地址?

[root@client ~ 18:59:24]# cat ipv4.sh
0.0.0.0
1.1.1.1
11.11.11.111
111.111.111.111
999.9.9.9
01.1.1.1
10.0.0.0
0.1.1.1
266.1.1.1
248.1.1.1
256.1.1.1
[root@client ~ 18:59:27]# cat ipv4.sh |egrep '\\b(([1-9][0-9]?)|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))(\\.(([1-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))){3}\\b'
1.1.1.1
11.11.11.111
111.111.111.111
10.0.0.0
248.1.1.1

10.反向引用(扩展学习)

对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。
每个缓冲区都可以使用 \\N 访问,其中 N 为一个标识特定缓冲区的一位或两位十进制数。
\\N 这用引用方式称之为反向引用。

[root@client ~ 19:02:19]# echo 'Is is the cost of of gasoline going up up?' | \\
> egrep -o '\\b([a-z]+) \\1\\b'
of of
up up

[root@client ~ 19:03:07]# echo 'Is is the cost of of of gasoline going up up?' | egrep -o '(\\b[a-z]+\\b\\s+)\\1{1,}'
of of of

[root@client ~ 19:16:42]# echo 'Is is the cost of of of gasoline going up up?' | egrep -o '(\\b[a-z]+\\b\\s+)\\1{1,}'
of of

二、grep 工具使用手册

1.grep 介绍

grep 是 Linux 系统中最重要的命令之一,其功能是从文本文件或管道数据流中筛选匹配的行及数据。
Linux操作文本的三大利器,简称三剑客,分别是:
• grep:擅长过滤。
• sed:擅长修改文本。
• awk:擅长格式化输出。

2.grep 命令语法

1.过滤管道:command | grep [OPTION]… PATTERNS

2.过滤文件:grep [OPTION]… PATTERNS [FILE]…

grep 命令帮助信息如下:

[root@client ~ 19:21:40]# grep –help
用法: grep [选项]... PATTERN [FILE]...
在每个 FILE 或是标准输入中查找 PATTERN。
默认的 PATTERN 是一个基本正则表达式(缩写为 BRE)
例如: grep -i 'hello world' menu.h main.c

正则表达式选择与解释:
-E, –extended-regexp PATTERN 是一个可扩展的正则表达式(缩写为 ERE)
-F, –fixed-strings PATTERN 是一组由断行符分隔的定长字符串。
-G, –basic-regexp PATTERN 是一个基本正则表达式(缩写为 BRE)
-P, –perl-regexp PATTERN 是一个 Perl 正则表达式
-e, –regexp=PATTERN 用 PATTERN 来进行匹配操作
-f, –file=FILE 从 FILE 中取得 PATTERN
-i, –ignore-case 忽略大小写
-w, –word-regexp 强制 PATTERN 仅完全匹配字词
-x, –line-regexp 强制 PATTERN 仅完全匹配一行
-z, –null-data 一个 0 字节的数据行,但不是空行

Miscellaneous:
-s, –no-messages suppress error messages
-v, –invert-match select non-matching lines
-V, –version display version information and exit
–help display this help text and exit

输出控制:
-m, –max-count=NUM NUM 次匹配后停止
-b, –byte-offset 输出的同时打印字节偏移
-n, –line-number 输出的同时打印行号
–line-buffered 每行输出清空
-H, –with-filename 为每一匹配项打印文件名
-h, –no-filename 输出时不显示文件名前缀
–label=LABEL 将LABEL 作为标准输入文件名前缀
-o, –only-matching show only the part of a line matching PATTERN
-q, –quiet, –silent suppress all normal output
–binary-files=TYPE assume that binary files are TYPE;
TYPE is 'binary', 'text', or 'without-match'
-a, –text equivalent to –binary-files=text
-I equivalent to –binary-files=without-match
-d, –directories=ACTION how to handle directories;
ACTION is 'read', 'recurse', or 'skip'
-D, –devices=ACTION how to handle devices, FIFOs and sockets;
ACTION is 'read' or 'skip'
-r, –recursive like –directories=recurse
-R, –dereference-recursive
likewise, but follow all symlinks
–include=FILE_PATTERN
search only files that match FILE_PATTERN
–exclude=FILE_PATTERN
skip files and directories matching FILE_PATTERN
–exclude-from=FILE skip files matching any file pattern from FILE
–exclude-dir=PATTERN directories that match PATTERN will be skipped.
-L, –files-without-match print only names of FILEs containing no match
-l, –files-with-matches print only names of FILEs containing matches
-c, –count print only a count of matching lines per FILE
-T, –initial-tab make tabs line up (if needed)
-Z, –null print 0 byte after FILE name

文件控制:
-B, –before-context=NUM 打印以文本起始的NUM 行
-A, –after-context=NUM 打印以文本结尾的NUM 行
-C, –context=NUM 打印输出文本NUM 行
-NUM same as –context=NUM
–group-separator=SEP use SEP as a group separator
–no-group-separator use empty string as a group separator
–color[=WHEN],
–colour[=WHEN] use markers to highlight the matching strings;
WHEN is 'always', 'never', or 'auto'
-U, –binary do not strip CR characters at EOL (MSDOS/Windows)
-u, –unix-byte-offsets report offsets as if CRs were not there
(MSDOS/Windows)

‘egrep’即‘grep -E’。‘fgrep’即‘grep -F’。
直接使用‘egrep’或是‘fgrep’均已不可行了。
若FILE 为 -,将读取标准输入。不带FILE,读取当前目录,除非命令行中指定了-r 选项。
如果少于两个FILE 参数,就要默认使用-h 参数。
如果有任意行被匹配,那退出状态为 0,否则为 1
如果有错误产生,且未指定 -q 参数,那退出状态为 2

请将错误报告给: bug-grep@gnu.org
GNU Grep 主页: <http://www.gnu.org/software/grep/>
GNU 软件的通用帮助: <http://www.gnu.org/gethelp/>

3.grep 命令选项

文件准备

[root@client ~ 19:26:03]# cat words
cat
category
acat
concatenate
cbt
c1t
cCt
c-t
c.t
dog

(1)模式选择和解释选项

-E 选项
支持扩展正则表达式,相当于 egrep 命令。

[root@client ~ 19:34:47]# echo dogdogdog >> words
[root@client ~ 19:35:25]# cat words | egrep '(dog){3}'
dogdogdog
[root@client ~ 19:35:27]# cat words | grep -E '(dog){3}'
dogdogdog

-e 选项
使用多个 -e 选项匹配多个PATTERNS。

[root@client ~ 19:35:38]# echo dogdog >> words
[root@client ~ 19:36:36]# echo dogdogdogdog >> words
[root@client ~ 19:36:42]# cat words | grep -e 'cat' -e 'dog'
cat
category
acat
concatenate
dog
dogdogdog
dogdog
dogdogdogdog
[root@client ~ 19:36:51]# cat words | egrep 'cat|dog'
cat
category
acat
concatenate
dog
dogdogdog
dogdog
dogdogdogdog

-f 选项
从文件读取多个 PATTERNS。

[root@client ~ 19:37:00]# echo -e 'cat\\ndog' > pattens_file
[root@client ~ 19:37:38]# cat pattens_file
cat
dog
[root@client ~ 19:37:46]# cat words | grep -f pattens_file
cat
category
acat
concatenate
dog
dogdogdog
dogdog
dogdogdogdog

-i 选项
忽略大小写匹配。

[root@client ~ 19:37:54]# cat words | grep -i 'cBt'
cbt

-w 选项
匹配整个单词。

[root@client ~ 19:38:45]# cat words | grep -w 'cat'
cat
# 或者
[root@client ~ 19:39:14]# cat words | grep '\\bcat\\b'
cat

-x 选项

匹配整行。

[root@client ~ 19:39:20]# cat words | grep -x 'cat'
cat
# 或者
[root@client ~ 19:40:17]# cat words | grep '^cat$'
cat

(2)输出控制选项

-v 选项
反向匹配,显示与PATTERNS不匹配的项目。

[root@client ~ 20:21:42]# cat words | egrep -v '^d|^c'
acat
hello cat

# 不看注释行和空白行
[root@client ~ 20:21:51]# egrep -v '^\\s*#|^$' /etc/profile

-m 选项
控制最大匹配数目,匹配特定次数后停止匹配。

[root@client ~ 20:22:00]# cat words | grep 'dog'
dog
dogdog
dogdogdog
dogdogdogdog

[root@client ~ 20:22:51]# cat words | grep -m2 'dog'
dog
dogdog

-c 选项
显示匹配到项目的数量。

[root@client ~ 20:22:59]# cat words | grep -c 'dog'
4

-b 选项
显示匹配项目的字节偏移量。

[root@client ~ 20:23:33]# head -5 words
cat
category
acat
concatenate
dog

[root@client ~ 20:24:02]# cat words | grep -b 'cat'
0:cat
4:category
13:acat
18:concatenate
64:hello cat

-n 选项
显示匹配项目的行号。

[root@client ~ 20:24:16]# cat words | grep -n 'cat'
1:cat
2:category
3:acat
4:concatenate
9:hello cat

-o 选项
只显示匹配到的内容,行中其他内容不显示。

[root@client ~ 20:25:14]# cat words | egrep '(dog){3}'
dogdogdog
dogdogdogdog
[root@client ~ 20:25:44]# cat words | egrep -o '(dog){3}'
dogdogdog
dogdogdog

-q 选项
不显示任何正常输出。一般用于脚本判定文件中是否包含特定内容。
通过特殊变量 $? 查看是否匹配到内容。

# 找到的情况
[root@client ~ 20:25:52]# cat words | egrep -q '(dog){3}'
[root@client ~ 20:26:40]# echo $?
0

# 找不到的情况
[root@client ~ 20:26:47]# cat words | egrep -q '(dog){3}asdfasfdasf'
[root@client ~ 20:26:56]# echo $?
1

-s 选项
不显示任何错误输出。

[lz@client ~ 20:28:05]$ grep '^SELINUX=' /etc/shadow /etc/selinux/config
grep: /etc/shadow: 权限不够
/etc/selinux/config:SELINUX=disabled

[lz@client ~ 20:28:10]$ grep -s '^SELINUX=' /etc/shadow /etc/selinux/config
/etc/selinux/config:SELINUX=disabled

(3)查找文件选项

-r -R 选项

  • -r,递归匹配目录。
  • -R,递归匹配目录,跟随软链接。

[lz@client ~ 20:28:17]$ grep -r '^SELINUX=' -s /etc
/etc/selinux/config:SELINUX=disabled

-h 和 -H 选项
• -h,不显示匹配项目所在文件的文件名。
• -H,显示匹配项目所在文件的文件名,默认情况使用该选项。

[lz@client ~ 20:30:06]$ grep -r '^SELINUX=' -s -h /etc
SELINUX=disabled
[lz@client ~ 20:30:58]$ grep -r '^SELINUX=' -s -H /etc
/etc/selinux/config:SELINUX=disabled

-l 和 -L 选项
• -l,对目录匹配时,只显示那些 包含匹配模式的文件的名称。
• -L,对目录匹配时,只显示那些 不 包含匹配模式的文件的名称。

[lz@client ~ 20:31:06]$ grep -r '^SELINUX=' -s -l /etc
/etc/selinux/config
[lz@client ~ 20:31:41]$ grep -r '^SELINUX=' -s -L /etc | tail -5
/etc/hostname
/etc/.updated
/etc/aliases.db
/etc/vimrc
/etc/rsyncd.conf

(4)输出内容控制选项

-B 选项
显示匹配项目本身,以及前多少行。

[lz@client ~ 20:31:49]$ ip addr | grep '10.1.8.11' -B2
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:b0:ec:b1 brd ff:ff:ff:ff:ff:ff
inet 10.1.8.11/24 brd 10.1.8.255 scope global noprefixroute ens33

-A 选项

显示匹配项目本身,以及后多少行。

[lz@client ~ 20:33:27]$ ip addr |grep 'ens33:' -A2
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:b0:ec:b1 brd ff:ff:ff:ff:ff:ff
inet 10.1.8.11/24 brd 10.1.8.255 scope global noprefixroute ens33

-C 选项
显示匹配项目本身,以及前后多少行。

[lz@client ~ 20:33:31]$ ip addr |grep 'ens33:' -C2
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:b0:ec:b1 brd ff:ff:ff:ff:ff:ff
inet 10.1.8.11/24 brd 10.1.8.255 scope global noprefixroute ens33

三、sed 工具使用手册

1.sed 介绍

sed,英文全称 stream editor ,是一种非交互式的流编辑器,能够实现对文本非交互式的处理,功能很强大。
Linux操作文本的三大利器,简称三剑客,分别是:
• grep:擅长过滤。
• sed:擅长修改文本。
• awk:擅长格式化输出。

2.sed 工作流程

读取行 –> 执行 –> 显示 –> 读取行 –> 执行 –> 显示 –> ....> 读取行 –> 执行 –> 显示

在这里插入图片描述

1.读取行
sed 从输入流 (文件、管道、标准输入流)中读取 一行 并存储在名叫 pattern space 的内部空间中。
sed 是行文字处理器。每次只会读取一行。
sed 内部会有一个计数器,记录着当前已经处理多少行,也就是当前行的行号。

2.执行
按照 sed 命令定义的顺序依次应用于刚刚读取的 一行 数据。
默认情况下,sed 一行一行的处理所有的输入数据。但如果我们指定了行号,则只会处理指定的行。

3.显示
把经过 sed 命令处理的数据发送到输出流(文件、管道、标准输出),并同时清空 pattern space 空间。

4.上面流程一直循环,直到输入流中的数据全部处理完成。

3.sed 注意事项

整个流程看似简单,有几个知识点需要注意:
• pattern space 空间是 sed 在内存中开辟的一个私有的存储区域。内存的特性,会导致关闭命令行或关机数据就没了。
• 默认情况下,sed 命令只会处理 pattern space 空间中的数据,且并不会将处理后的数据保存到源文件中。也就是说,sed 默认并不会修改源文件。
但 GNU SED 提供提供了一种方式用于修改 源文件。方式就是传递 -i 选项,在后面的章节中介绍。
• sed 还在内存上开辟了另一个私有的空间 hold space 用于保存处理后的数据以供以后检索。
每一个周期执行结束,sed 会清空 pattern space 空间的内容,但 hold space 空间的内容并不会清空。hold space 空间用于存储处理后数据,sed 命令并不会对这里的数据处理。
这样,当 sed 需要之前处理后的数据时,可以随时从 hold space 空间读取。
• sed 程序执行前,模式 pattern 和 hold space 空间都是空的。
• 如果我们没有传递任何输入文件,sed 默认会从 标准输入 中读取数据。
• sed 可以指定只处理输入数据中的行范围。默认情况下是全部行,因此会依次处理每一行。

4.sed 命令语法

sed 帮助

[lz@client ~ 20:33:40]$ sed –help
用法: sed [选项]... {脚本(如果没有其他脚本)} [输入文件]...

-n, –quiet, –silent
取消自动打印模式空间
-e 脚本, –expression=脚本
添加“脚本”到程序的运行列表
-f 脚本文件, –file=脚本文件
添加“脚本文件”到程序的运行列表
–follow-symlinks
直接修改文件时跟随软链接
-i[SUFFIX], –in-place[=SUFFIX]
edit files in place (makes backup if SUFFIX supplied)
-c, –copy
use copy instead of rename when shuffling files in -i mode
-b, –binary
does nothing; for compatibility with WIN32/CYGWIN/MSDOS/EMX (
open files in binary mode (CR+LFs are not treated specially))
-l N, –line-length=N
指定“l”命令的换行期望长度
–posix
关闭所有 GNU 扩展
-r, –regexp-extended
在脚本中使用扩展正则表达式
-s, –separate
将输入文件视为各个独立的文件而不是一个长的连续输入
-u, –unbuffered
从输入文件读取最少的数据,更频繁的刷新输出
-z, –null-data
separate lines by NUL characters
–help
display this help and exit
–version
output version information and exit

如果没有 -e, –expression, -f–file 选项,那么第一个非选项参数被视为
sed脚本。其他非选项参数被视为输入文件,如果没有输入文件,那么程序将从标准
输入读取数据。
GNU sed home page: <http://www.gnu.org/software/sed/>.
General help using GNU software: <http://www.gnu.org/gethelp/>.
E-mail bug reports to: <bug-sed@gnu.org>.
Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.

sed 命令语法简写格式如下:

sed [option] [sed-command] [input-file]

总的来说 sed 命令主要由四部分构成:

  • sed 命令。
  • [option] 命令行选项,用于改变 sed 的工作流程。
  • [sed-command] 是具体的 sed 命令。
  • [input-file] 输入数据,如果不指定,则默认从标准输入中读取。
  • 示例1:模拟cat命令打印文件内容

    [lz@client ~ 20:37:07]$ cat > data.txt <<'EOF'
    > I am studing sed
    > I am www.lz.cloud
    > I am a Superman
    > I am a so handsome
    > EOF

    [lz@client ~ 20:39:36]$ sed '' data.txt
    I am studing sed
    I am www.lz.cloud
    I am a Superman
    I am a so handsome

    对照着 sed 命令的语法格式:
    • 这里未使用 option。
    • ‘’ ,对应着 [sed-command] 为具体的 sed 语句。
    • data.txt ,对应着 [input-file],用于提供输入数据。

    示例2:从标准输入中读取数据
    如果我们没有提供输入文件,那么 sed 默认会冲标准输入中读取数据。

    [lz@client ~ 20:39:47]$ sed ''
    # 输入hello world,并回车
    hello world
    # 输出hello world
    hello world
    # 按ctrl+d退出

    -e 选项
    从命令行读取sed命令,我们需要将 sed 命令使用单引号 ( ‘’ ) 引起来。

    # 打印data.txt文件内容
    [lz@client ~ 21:01:47]$ sed -e '' data.txt

    # 如果只有一个命令,-e选项可以省略
    [lz@client ~ 21:02:01]$ sed '' data.txt

    # -e 选项可以多次使用,1d是作用是删除第一行
    [lz@client ~ 21:02:10]$ sed -e '1d' -e '2d' -e '5d' data.txt
    I am a Superman
    I am so handsome
    # 因为不存在第五行,所以也就没删除的效果

    # 使用分号(;)分开多个命令
    [lz@client ~ 21:02:11]$ sed -e '1d;2d;5d' data.txt
    I am a Superman
    I am so handsome

    -f 选项
    sed 还支持把所有 sed 命令保存在一个普通的文本文件里,然后通过 -f 选项来运行这个文件。
    当把 sed 存储在文件中时,需要注意 每一个 sed 命令独自成一行。
    文件的作用仅仅用于存储命令而已,因此存储 sed 命令的文件并没有任何特殊,可以是一个 .txt 文本文件。

    [lz@client ~ 21:02:31]$ echo -e "1d\\n2d\\n5d" > scripts
    [laoma@shell ~]$ cat scripts
    1d
    2d
    5d
    [lz@client ~ 21:02:40]$ sed -f scripts data.txt
    I am a Superman
    I am so handsome

    -n 选项
    如果指定了该选项,那么模式空间数据将不会自动打印,需要明确指明打印才会输出记录。

    # 以下命令没有任何输出
    [lz@client ~ 21:04:59]$ sed -n '' data.txt

    # 打印第一行记录
    [lz@client ~ 21:05:08]$ sed -n '1p' data.txt
    I am studing sed

    5.sed 行寻址

    作用
    通过行寻址匹配要处理的输入流。
    语法
    这里以打印命令p为例。
    语法:[address1[,address2]]p
    • address1 和 address2 分别是 起始地址 和 结束地址,可以是 行号或 模式字符串。
    • address1 和 address2 都是可选参数,可以都不填,这时候就是打印所有行,从文件的开头到文件结束。
    • 如果存在一个,那么就是打印 单行。也就是只打印 address1 指定的那行。
    • p 命令仅从 模式缓冲区 中打印行,也就是该行不会发送到输出流,原始文件保持不变。
    示例文件

    [lz@client ~ 21:05:23]$ echo 'This is 1
    > This is 2
    > This is 3
    > This is 4
    > This is 5 '
    > test

    演示
    示例1: 打印所有行

    # 打印所有行
    [lz@client ~ 21:07:53]$ cat test | sed ''
    # 输出结果
    This is 1
    This is 2
    This is 3
    This is 4
    This is 5

    # sed 默认打印模式缓冲区中所有内容。
    # 等效于
    [lz@client ~ 21:08:33]$ cat test | sed -n 'p'
    # -n 关闭sed打印模式缓冲区中所有内容。
    # p命令,明确打印输出模式缓冲区中所有内容。

    示例2: 打印特定行

    # 打印第1行
    [lz@client ~ 21:08:40]$ cat test | sed -n '1p'
    # 输出结果
    This is 1

    # 打印第最后一行
    [lz@client ~ 21:09:53]$ cat test | sed -n '$p'
    # 输出结果
    This is 5

    示例3: 打印第1行到3行

    [lz@client ~ 21:10:00]$ cat test | sed -n '1,3p'
    # 输出结果
    This is 1
    This is 2
    This is 3

    示例4: 打印第3行到最后一行

    [lz@client ~ 21:11:10]$ cat test | sed -n '3,$p'
    # 输出结果
    This is 3
    This is 4
    This is 5

    示例5: 连续输出,打印第2行以及后续两行

    [lz@client ~ 21:12:13]$ cat test | sed -n '2,+2p'
    # 输出结果
    This is 2
    This is 3
    This is 4

    示例6: 隔行输出,打印第1行以及后续隔2行输出

    [lz@client ~ 21:12:58]$ cat test | sed -n '1~2p'
    # 输出结果
    This is 1
    This is 3
    This is 5

    6.sed 模式寻址

    sed 除了可以从行号来选择行,s还支持模式查找指定的行。
    • 模式 可以是一个普通的字符串或者一个正则表达式。
    • 模式 的语法和行寻址的语法类似,只是把行号换成了 模式 匹配。
    例如,输出匹配指定模式的行,语法格式如下:

    /pattern/

    示例文件

    [lz@client ~ 21:13:38]$ cat << 'EOF' > ~/test
    > root:x:0:0:root:/root:/bin/bash
    > bin:x:1:1:bin:/bin:/bin/false
    > daemon:x:2:2:daemon:/sbin:/bin/false
    > mail:x:8:12:mail:/var/spool/mail:/bin/false
    > ftp:x:14:11:ftp:/home/ftp:/bin/false
    > &nobody:$:99:99:nobody:/:/bin/false
    > zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash
    > http:x:33:33::/srv/http:/bin/false
    > dbus:x:81:81:System message bus:/:/bin/false
    > hal:x:82:82:HAL daemon:/:/bin/false
    > mysql:x:89:89::/var/lib/mysql:/bin/false
    > aaa:x:1001:1001::/home/aaa:/bin/bash
    > ba:x:1002:1002::/home/zhangy:/bin/bash
    > test:x:1003:1003::/home/test:/bin/bash
    > @zhangying:*:1004:1004::/home/test:/bin/bash
    > policykit:x:102:1005:Po
    > EOF

    演示
    示例1: 打印含有字符串zhang的行

    [lz@client ~ 21:16:41]$ cat test | sed -n '/zhang/p'
    zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash
    ba:x:1002:1002::/home/zhangy:/bin/bash
    @zhangying:*:1004:1004::/home/test:/bin/bash

    示例2: 打印root开头的行到zhang开头的行

    [lz@client ~ 21:17:11]$ cat test | sed -n '/^root/,/^mail/p'
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/bin/false
    daemon:x:2:2:daemon:/sbin:/bin/false
    mail:x:8:12:mail:/var/spool/mail:/bin/false

    示例3: 打印root开头的行到第三行

    [lz@client ~ 21:17:45]$ cat test | sed -n '/^root/,3p'
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/bin/false
    daemon:x:2:2:daemon:/sbin:/bin/false

    示例4: 打印root开头的行到最后一行

    [lz@client ~ 21:18:18]$ cat test | sed -n '/^root/,$p'

    7.sed 子命令

    打印
    作用
    • p,打印模式空间所有记录。
    • P,打印模式空间第一行记录。
    语法
    格式:[address1[,address2]]p
    • address1 和 address2 分别是 起始地址 和 结束地址,可以是 行号或 模式字符串。
    • address1 和 address2 都是可选参数,可以都不填,这时候就是打印所有行,从文件的开头到文件结束。
    • 如果存在一个,那么就是打印 单行。也就是只打印 address1 指定的那行。
    • p 命令仅从 模式缓冲区 中打印行,也就是该行不会发送到输出流,原始文件保持不变。
    示例

    [lz@client ~ 21:18:47]$ echo 'This is 1
    > This is 2
    > This is 3'
    | sed -n '1{N;p}'

    # 输出结果
    This is 1
    This is 2
    [lz@client ~ 21:19:30]$ echo 'This is 1
    > This is 2
    > This is 3'
    | sed -n '1{N;P}'
    # 输出结果
    This is 1

    读取下一行
    • n,提前读取下一行,覆盖模型空间之前读取的行。模型空间之前读取的行并没有删除,依然打印至标准输出,除非使用-n选项指明不打印。
    示例1:打印偶数行内容

    [lz@client ~ 21:19:41]$ echo 'This is 1
    > This is 2
    > This is 3
    > This is 4
    > This is 5'
    | sed -n 'n;p'
    # 输出内容
    This is 2
    This is 4

    说明:
    • 读取 This is 1,执行n命令,此时模式空间为This is 2,执行p,打印模式空间内容This is 2。
    • 之后读取 This is 3,执行 n 命令,此时模式空间为This is 4,执行p,打印模式空间内容This is 4。
    • 之后读取 This is 5,执行 n 命令,因为后续没有内容了,所以退出,并放弃p命令。
    因此,最终打印出来的就是偶数行。
    • N,简单来说就是追加下一行到模式空间,同时将两行看做一行,但是两行之间依然含有\\n换行符。
    示例1: 成对合并行

    [lz@client ~ 21:20:48]$ cat test | sed 'N;s/\\n/==/'
    root:x:0:0:root:/root:/bin/bash==bin:x:1:1:bin:/bin:/bin/false
    daemon:x:2:2:daemon:/sbin:/bin/false==mail:x:8:12:mail:/var/spool/mail:/bin/false
    ......

    说明:

  • N,追加下一行到当前行后面,组成一个新行来处理。
  • s/\\n//,将新行中 \\n 换行符替换成,末尾的换行符不替换。
  • 示例2: 打印前2行

    [lz@client ~ 21:21:40]$ echo 'This is 1
    > This is 2
    > This is 3
    > This is 4
    > This is 5'
    | sed -n '1{N;p}'
    This is 1
    This is 2

    替换

    **示例1:**把test文件中的root替换成tankzhang,只不过只替换一次即终止在这一行的操作,并转到下一行

    [lz@client ~ 21:22:28]$ sed 's/root/tankzhang/' test | grep tankzhang
    tankzhang:x:0:0:root:/root:/bin/bash

    关闭 SELinux

    [root@client ~ 21:25:28]# sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config

    示例2:把test文件中的root全部替换成tankzhang。字母g是global的缩写。

    [lz@client ~ 21:27:00]$ sed 's/root/tankzhang/g' test |grep tankzhang
    tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash

    示例3:加了-n和p后表示只打印那些发生替换的行(部分替换),下面的例子,不需要使用grep命令。

    [lz@client ~ 21:27:05]$ sed -n 's/root/tankzhang/p' test
    tankzhang:x:0:0:root:/root:/bin/bash

    示例4:加了-n和pg后表示只打印那些发生替换的行(全部替换)

    [lz@client ~ 21:28:03]$ sed -n 's/root/tankzhang/gp' test
    tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash

    示例5:在第二行到第八行之间,替换以zhang开头的行,用ying来替换,并显示替换的行

    [lz@client ~ 21:28:40]$ sed -ne '2,8s/^zhang/ying/gp' test
    yingy:x:1000:100:,,,:/home/zhangy:/bin/bash

    示例6: 从以zhang开头的行开始,到匹配Po的行结束,在他们之间进行替换

    [lz@client ~ 21:29:14]$ sed -ne '/^zhang/,/Po/ s/zhang/ying/gp' test
    yingy:x:1000:100:,,,:/home/yingy:/bin/bash
    ba:x:1002:1002::/home/yingy:/bin/bash
    @yingying:*:1004:1004::/home/test:/bin/bash

    替换中的分隔符可以自定义,默认是/。

    示例7: 自定义替换分隔符为 #。

    [lz@client ~ 21:29:47]$ sed -n 's#root#hello#gp' test
    hello:x:0:0:hello:/hello:/bin/bash

    其他替换

    [lz@client ~ 21:31:46]$ cat test1.txt
    my my my my my
    my my my my my
    my my my my my

    #替换每行第3个my
    [lz@client ~ 21:31:50]$ sed "s/my/your/3" test1.txt
    my my your my my
    my my your my my
    my my your my my

    #只替换第3行的第1个my
    [lz@client ~ 21:32:01]$ sed "3s/my/your/1" test1.txt
    my my my my my
    my my my my my
    your my my my my

    #只替换每行的第3个及以后的my
    [lz@client ~ 21:32:09]$ sed 's/my/your/3g' test1.txt
    my my your your your
    my my your your your
    my my your your your

    分隔符 ; 和 -e 选项
    需要执行多个sed处理命令时,用分号分开,或者使用 -e 选项。
    示例:
    • 在第2行到第8行之间,替换以zhang开头的行,用ying来替换
    • 在第5行到第10行之间,用goodbay来替换dbus,并显示替换的行

    [lz@client ~ 21:32:18]$ cat test | sed -n '2,8s/^zhang/ying/gp;5,10s#dbus#goodbay#gp'
    yingy:x:1000:100:,,,:/home/zhangy:/bin/bash
    goodbay:x:81:81:System message bus:/:/bin/false

    [lz@client ~ 21:33:41]$ cat test | sed -ne '2,8s/zhang/ying/gp' -ne '5,10s#dbus#goodbay#gp'
    yingy:x:1000:100:,,,:/home/yingy:/bin/bash
    goodbay:x:81:81:System message bus:/:/bin/false

    插入
    a(append)在匹配行下面插入新行

    [lz@client ~ 21:33:52]$ sed '/root/a====aaaa====' test
    root:x:0:0:root:/root:/bin/bash
    ====aaaa====
    bin:x:1:1:bin:/bin:/bin/false
    ......

    i(insert)在匹配行上面插入新行

    [lz@client ~ 21:34:39]$ sed '/root/i====iiii====' test
    ====iiii====
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/bin/false
    ......

    删除
    作用
    • d,删除模式空间所有记录。
    • D,删除模式空间第一行记录。
    语法
    d 格式:[address1[,address2]]d
    D 格式:[address1[,address2]]D
    • address1 和 address2 分别是 起始地址 和 结束地址,可以是 行号或 模式字符串。
    • address1 和 address2 都是可选参数,可以都不填,这时候就是删除所有行,从文件的开头到文件结束。
    • 如果存在一个,那么就是删除 单行。也就是只删除 address1 指定的那行。
    • d 命令仅从 模式缓冲区 中删除行,也就是该行不会发送到输出流,原始文件保持不变。

    d 删除 示例
    示例1: 删除1-14行

    [lz@client ~ 21:44:10]$ sed -e '1,14d' test
    @zhangying:*:1004:1004::/home/test:/bin/bash
    policykit:x:102:1005:Po

    示例2: 删除4以后的行,包括第4行,把$当成最大行数就行了。

    [lz@client ~ 21:52:02]$ sed -e '4,$d' test
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/bin/false
    daemon:x:2:2:daemon:/sbin:/bin/false

    示例3: 删除包括false的行,或者包括bash的行,别忘了加\\

    [lz@client ~ 21:52:37]$ sed -re '/(false|bash)/d' test
    policykit:x:102:1005:Po

    示例4: 删除从匹配root的行,到匹配以test开头的行,中间的行

    [lz@client ~ 21:53:10]$ sed -e '/root/,/^test/d' test
    @zhangying:*:1004:1004::/home/test:/bin/bash
    policykit:x:102:1005:Po

    更改
    整行替换。
    示例:root开头行替换成hello

    [lz@client ~ 21:53:23]$ sed '/^root/chello' test
    hello
    bin:x:1:1:bin:/bin:/bin/false
    daemon:x:2:2:daemon:/sbin:/bin/false
    ......

    # 等效下面命令
    [lz@client ~ 21:54:13]$ sed 's/^root.*/hello/' test

    四、awk 工具使用手册

    1.awk 介绍

    awk 是一个强大的文本分析工具。
    awk 是取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
    awk 更像一门编程语言,他可以自定义变量,有条件语句,有循环,有数组,有正则,有函数等。
    awk 按行读取数据,根据给出的条件进行查找,并在找出来的行中进行操作。

    2.awk 命令

    awk 命令格式
    awk [options] ‘script’ file(s)
    awk [options] -f scriptfile file(s)

  • script,定义如何处理数据。
  • file,是 awk 处理的数据来源,awk 也可以来自其它命令的输出。
  • -f scriptfile 从脚本文件中读取awk命令,每行都是一个独立的script。
    script 格式如下:
  • BEGIN { action }
    pattern { action }
    END { action }

    脚本通常是被单引号或双引号包住,一个awk脚本通常由四部分组成:

  • BEGIN { action } 语句块,awk 执行 pattern { action } 前要执行的脚本。
  • pattern { action } 语句块,决定动作语句何时触发,可以是以下任意一种: – 正则表达式:使用通配符的扩展集。 – 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。 – 模式匹配表达式:使用运算符~(匹配)和 ~!(不匹配)。
  • END { action } 语句块,awk 执行 pattern { action } 后要执行的脚本。
  • action部分,决定对数据如何处理,由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大刮号内。常见的action包括:变量或数组赋值、输出命令、内置函数、控制流语句。
    BEGIN { action }、pattern { action }、END { action }都是可选项目。
  • awk 工作流

    在这里插入图片描述

    • 第一步: 执行 BEGIN { commands } 语句块中的语句。
    在awk从输入输出流中读取行之前执行,通常在BEGIN语句块中执行如变量初始化,打印输出表头等操作。
    • 第二步:从文件或标准输入中读取一行,然后执行 pattern { commands }语句块。它逐行读取数据,从第一行到最后一行重复这个过程,直到读取完所有行。
    pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行。
    {} 类似一个循环体,会对文件中的每一行进行迭代,通常将变量初始化语句放在BEGIN语句块中,将打印结果等语句放在END语句块中。
    • 第三步:当读至输入流末尾时,执行 END { command }语句块。
    在awk从输入流中读取完所有的行之后执行,比如打印所有行的分析结果,它也是一个可选语句块。
    awk 示例
    示例文件

    [lz@client ~ 21:55:02]$ cat << 'EOF' > employee.txt
    > 1) 张三 技术部 23
    > 2) 李四 人力部 22
    > 3) 王五 行政部 23
    > 4) 赵六 技术部 24
    > 5) 朱七 客服部 23
    > EOF

    示例1: 打印雇员信息.

    [lz@client ~ 21:57:35]$ awk '{ print }' employee.txt
    1) 张三 技术部 23
    2) 李四 人力部 22
    3) 王五 行政部 23
    4) 赵六 技术部 24
    5) 朱七 客服部 23

    示例2: 通过读取awk脚本,打印雇员信息。

    [lz@client ~ 21:59:08]$ vim commands.awk
    [lz@client ~ 22:00:24]$ cat commands.awk
    { print }
    [lz@client ~ 22:00:27]$ awk -f commands.awk employee.txt
    1) 张三 技术部 23
    2) 李四 人力部 22
    3) 王五 行政部 23
    4) 赵六 技术部 24
    5) 朱七 客服部 23

    示例3: 输出特定隔行。

    [lz@client ~ 22:00:31]$ awk '/张三/ { print }' employee.txt
    1) 张三 技术部 23
    [lz@client ~ 22:01:49]$ awk '/张三/' employee.txt
    1) 张三 技术部 23

    示例4: 统计满足特定条件的记录数。
    AWK 中的所有变量都不需要初始化,并且会自动初始化为 0 。

    [lz@client ~ 22:01:57]$ awk '
    > /术/ { count=count+1 }
    > END { print "Count="count }'
    employee.txt
    #输出结果
    Count=2

    3.awk 命令选项

    –help 选项
    用于输出 awk 命令的帮助信息。

    [lz@client ~ 22:02:36]$ awk –help
    Usage: awk [POSIX or GNU style options] -f progfile [] file ...
    Usage: awk [POSIX or GNU style options] [] 'program' file ...
    POSIX options:GNU long options: (standard)
    -f progfile–file=progfile
    -F fs–field-separator=fs
    -v var=val–assign=var=val
    Short options:GNU long options: (extensions)
    -b–characters-as-bytes
    -c–traditional
    -C–copyright
    -d[file]–dump-variables[=file]
    -e 'program-text'–source='program-text'
    -E file–exec=file
    -g–gen-pot
    -h–help
    -L [fatal]–lint[=fatal]
    -n–non-decimal-data
    -N–use-lc-numeric
    -O–optimize
    -p[file]–profile[=file]
    -P–posix
    -r–re-interval
    -S–sandbox
    -t–lint-old
    -V–version

    To report bugs, see node `Bugs' in `gawk.info', which is
    section `Reporting Problems and Bugs'
    in the printed version.

    gawk is a pattern scanning and processing language.
    By default it reads standard input and writes standard output.

    Examples:
    gawk '{ sum += $1 }; END { print sum }' file
    gawk -F: '{ print $1 }' /etc/passwd

    -F 选项
    作用:用于定义awk程序的分隔符。awk程序的分隔符,是用于分割同一行数据的分割符号。默认分隔符是:空格。
    语法:-F fs 或者 –field-separator=fs

    -v 选项
    作用:用于预定义一些变量。这些预定义变量会在执行AWK 程序之前就定义好,准确的说,在 BEGIN 语句之前就已经定义。

    -p 选项
    作用:用于将当前的 awk 程序代码格式化并且输出到 file 文件中。
    格式:–profile[=file] 或者 -p[file]
    awk默认导出的 awk 程序代码格式化代码到 awkvars 文件中。

    4.awk 内置变量

    在上述的示例中,我们使用了很多 awk 内置变量。
    我们可以使用 -d 选项,导出awk内置的预定义变量到 file 文件中。
    格式:–dump-variables[=file] 或者-d[file]
    awk默认导出的内置的预定义变量保存在文件 awkvars 文件中。
    示例:

    [lz@client ~ 22:04:29]$ awk -d ''
    [lz@client ~ 22:05:38]$ cat awkvars.out
    ARGC: 1
    ARGIND: 0
    ARGV: array, 1 elements
    BINMODE: 0
    CONVFMT: "%.6g"
    ERRNO: ""
    FIELDWIDTHS: ""
    FILENAME: ""
    FNR: 0
    FPAT: "[^[:space:]]+"
    FS: " "
    IGNORECASE: 0
    LINT: 0
    NF: 0
    NR: 0
    OFMT: "%.6g"
    OFS: " "
    ORS: "\\n"
    RLENGTH: 0
    RS: "\\n"
    RSTART: 0
    RT: ""
    SUBSEP: "\\034"
    TEXTDOMAIN: "messages"

    我们把上面的输出结果整理如下:

    变量数据类型默认值
    ARGC number 1
    ARGIND number 0
    ARGV array 1 elements
    BINMODE number 0
    CONVFMT string “%.6g”
    ERRNO number 0
    FIELDWIDTHS string “”
    FILENAME string “”
    FNR number 0
    FS string " "
    IGNORECASE number 0
    LINT number 0
    NF number 0
    NR number 0
    OFMT string “%.6g”
    OFS string " "
    ORS string “\\n”
    RLENGTH number 0
    RS string “\\n”
    RSTART number 0
    RT string “”
    SUBSEP string “\\034”
    TEXTDOMAIN string “messages”

    上面列出的这些变量,在 AWK 中扮演整重要的作用。

    变 量描述
    ARGC 命令行参数的数目。
    ARGIND 命令行中当前文件的位置(从0开始算)。
    ARGV 包含命令行参数的数组。
    CONVFMT 数字转换格式(默认值为%.6g)
    ENVIRON 环境变量关联数组。
    ERRNO 最后一个系统错误的描述。
    FIELDWIDTHS 字段宽度列表(用空格键分隔)。
    FILENAME 当前文件名。
    FNR 同NR,但相对于当前文件。
    FS 字段分隔符(默认是任何空格)。
    IGNORECASE 如 果为真,则进行忽略大小写的匹配。
    NF 当前记录中的字段数。
    NR 当前记录数(读入第几行数据)。
    OFMT 数字的输出格式(默认值是%.6g)。
    OFS 输 出字段分隔符(默认值是一个空格)。
    ORS 输出记录分隔符(默认值是一个换行符)。
    RLENGTH 由 match函数所匹配的字符串的长度。
    RS 记录分隔符(默认是一个换行符)。
    RSTART 由 match函数所匹配的字符串的第一个位置。
    SUBSEP 数组下标分隔符(默认值是\\034)。
    $n 当前记录的第n个字段,字段间由 FS分隔。
    $0 完整的输入记录。

    5.NF 变量

    变量 NF 是 Number of Fields 的缩写,用于表示当前行分割出来的字段/列数量。

    下面的命令输出了当前每一行有被分割出了多少个字段。

    [lz@client ~ 22:05:45]$ echo -e "一 二\\n一 二 三\\n一 二 三 四" | awk '{ print $0 "\\t",NF }'
    #运行以上代码,输出结果如下:
    一 二 2
    一 二 三 3
    一 二 三 四 4

    变量 NF 还可以用于条件判断。
    例如,下面的命令输出了哪些字段/列大于 2 的行。

    [lz@client ~ 22:10:42]$ echo -e "一 二\\n一 二 三\\n一 二 三 四" | awk 'NF > 2'
    #运行以上代码,输出结果如下:
    一 二 三
    一 二 三 四

    6.NR 变量

    变量 NR 是 Number of Record 的缩写,用于表示当前行的行号,也就是处理到第几行。行编号从 1 开始。
    下面的代码,用于在每一行数据的前面输出当前的行号

    [lz@client ~ 22:11:41]$ echo -e "一 二\\n一 二 三\\n一 二 三 四" | awk '{ print NR". "$0 }'
    #运行以上代码,输出结果如下:
    1. 一 二
    2. 一 二 三
    3. 一 二 三 四

    变量 NR 还可以用于条件判断,例如下面的命令用于输出行号小于 3 的行,也就是第一第二行。

    [lz@client ~ 22:12:44]$ echo -e "一 二\\n一 二 三\\n一 二 三 四" | awk 'NR < 3'
    #运行以上代码,输出结果如下:
    一 二
    一 二 三

    $N

    对于 AWK 来说,默认的分割符是空白符号,包括 “\\t” 和空格 " "。当 AWK 使用分割符对每一行进行分割后,会对每一列/字段进行编号:
    • $1 $2 $3 …,分别代表第1列,第2列,第3列…
    • $0 ,代表一整行。

    7.awk 运算符

    运算符描述
    =、+=、-=、*=、/=、%=、^=、**= **赋值运算符:**直接赋值、加赋值、减赋值、乘赋值、除赋值、求余赋值、求幂赋值
    +、-、*、/、%、^、 **算数运算符:**加、减、乘、除、求余、求幂
    ++、– **自增和自减运算符:**自增1、自减1,作为前缀或后缀
    +、- **一元运算符:**一元加、一元减
    <、<=、>、>=、==、!= **关系运算符:**小于、小于等于、大于、大于等于、等于、不等于
    、! **正则表达式运算符:**匹配和不匹配
    &&、||、! **逻辑运算符:**逻辑与、逻辑或、逻辑非

    [lz@client ~ 22:15:54]$ awk 'BEGIN { x=5;x=x+2;print "x=",x }'
    x=7
    [lz@client ~ 22:16:04]$ awk 'BEGIN { x=5;x=x-2;print "x=",x }'
    x=3
    [lz@client ~ 22:16:11]$ awk 'BEGIN { x=5;x=x*2;print "x=",x }'
    x=10
    [lz@client ~ 22:16:18]$ awk 'BEGIN { x=5;x=x/2;print "x=",x }'
    x=2.5
    [lz@client ~ 22:16:20]$ awk 'BEGIN { x=5;x=x%2;print "x=",x }'
    x=1
    [lz@client ~ 22:16:24]$ awk 'BEGIN { x=5;x=x^2;print "x=",x }'
    x=25
    [lz@client ~ 22:16:56]$ awk 'BEGIN { x=5;x=x**2;print "x=",x }'
    x=25

    赞(0)
    未经允许不得转载:171主机测评 » Linux正则+三剑客详解,日常文本处理效率翻倍
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址