Linux 正则表达式

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

正则表达式分类:

  • 普通正则表达式
  • 扩展正则表示,支持更多的元字符。

环境准备

[root@server ~ 09:46:28]#  cat > words <<EOF
> cat
> category
> acat
> concatenate
> cbt
> c1t
> cCt
> c-t
> c.t
> dog
> EOF

普通字符

[root@server ~ 10:04:57]# cat words | grep cat
cat
category
acat
concatenate

字符集

.

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

[root@server ~ 10:15:49]# cat words | grep 'c.t'
cat
category
acat
concatenate
cbt
c1t
cCt
c-t
c.t

[…]

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

[root@server ~ 10:16:00]# cat words | grep 'c[ab]t'
cat
category
acat
concatenate
cbt

[a-z] [A-Z] [0-9]

  • [a-z],匹配所有小写字母。
  • [A-Z],匹配所有大写字母。
  • [0-9],匹配所有数字。
[root@server ~ 10:16:23]# cat words | grep 'c[a-z]t'
cat
category
acat
concatenate
cbt
[root@server ~ 10:16:29]# cat words | grep 'c[A-Z]t'
cCt
[root@server ~ 10:16:35]# cat words | grep 'c[0-9]t'
c1t
[root@server ~ 10:16:40]# cat words | grep 'c[a-z0-9]t'
cat
category
acat
concatenate
cbt
c1t
[root@server ~ 10:16:49]# cat words | grep 'c[a-zA-Z0-9]t'
cat
category
acat
concatenate
cbt
c1t
cCt
# 要想匹配-符号,将改符号写在第一个位置
[root@server ~ 10:17:46]# cat words | grep 'c[-a-zA-Z0-9]t'
cat
category
acat
concatenate
cbt
c1t
cCt
c-t

[^…]

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

[root@server ~ 10:17:55]# cat words | grep 'c[^ab]t'
c1t
cCt
c-t
c.t
# ^放中间会被当做普通字符
[root@server ~ 10:18:11]# cat words | grep 'c[a^b]t'
cat
category
acat
concatenate
cbt

### \

将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。

例如, ‘n’ 匹配字符 ‘n’。\n 匹配换行符。序列 \\ 匹配 \,而 \( 则匹配 (

[root@server ~ 10:18:34]# cat words | grep 'c\.t'
c.t
# 匹配普通字符,虽然可以匹配,但强烈建议不要在前面加\
[root@server ~ 10:18:50]# cat words | grep 'c\at'
cat
category
acat
concatenate

字符集总结

选项 描述
[[:digit:]] 数字: 0 1 2 3 4 5 6 7 8 9 等同于[0-9]
[[:xdigit:]] 十六进制数字: 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f 等同于[0-9a-fA-F]
[[:lower:]] 小写字母:在 C 语言环境和ASCII字符编码中,对应于[a-z]
[[:upper:]] 大写字母:在 C 语言环境和ASCII字符编码中,对应于[A-Z]
[[:alpha:]] 字母字符:[[:lower:]和[[:upper:]];在C语言环境和ASCII字符编码中,等同于**[A-Za-z]**
[[:alnum:]] 字母数字字符:[:alpha:]和[:digit:];在C语言环境和ASCII字符编码中,等同于**[0-9A-Za-z]**
[[:blank:]]或者[[:space:]] 空白字符:在 C 语言环境中,它对应于制表符、换行符、垂直制表符、换页符、回车符和空格。
[[:punct:]] 标点符号:在C语言环境和ASCII字符编码中,它对应于!" # $ % &'()*+,-./:;<=>?@[]^_`{|}~
[[:print:]]或者 [[:graph:]] 可打印字符: [[:alnum:]]、[[:punct:]]。
[[:cntrl:]] 控制字符。在 ASCII中, 这些字符对应八进制代码000到037和 177 (DEL)。

非打印字符

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

字符 描述
\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

定位符

^

匹配行首位置。

[root@server ~ 10:19:03]# cat words |grep '^cat'
cat
category

$

匹配行末位置。

[root@server ~ 10:20:31]# cat words |grep 'cat$'
cat
acat

\b

匹配一个单词边界。

[root@server ~ 10:20:48]# echo hello cat kitty >> words
[root@server ~ 10:21:14]# cat words |grep '\bcat'
cat
category
[root@server ~ 10:21:32]# cat words |grep 'cat\b'
cat
acat
[root@server ~ 10:21:49]# cat words | grep '\bcat\b'
cat
hello cat kitty

\B

非单词边界匹配。

[root@server ~ 10:22:08]# cat words |grep '\Bcat\B'
concatenate

< 和 >

  • \< ,匹配一个单词左边界。
  • \>,匹配一个单词右边界。
[root@server ~ 10:23:04]# cat words |grep '\<cat'
cat
category
hello cat kitty

[root@server ~ 11:12:08]# cat words |grep 'cat\>'
cat
acat
hello cat kitty

限定次数

*

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

[root@server ~ 11:12:27]# echo dg>> words
[root@server ~ 11:12:55]# echo doog>> words
[root@server ~ 11:13:00]# cat words |grep 'do*g'
dog
dg
doog

+

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

[root@server ~ 11:13:52]# cat words | egrep 'do+g'
dog
doog

?

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

[root@server ~ 11:13:58]# cat words | egrep 'do?g'
dog
dg

{n}

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

[root@server ~ 11:14:33]# cat words | egrep 'do{2}g'
doog

{m,n}

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

[root@server ~ 11:14:36]# echo dooog >> words
[root@server ~ 11:14:48]# echo doooog >> words

[root@server ~ 11:14:54]# cat words | grep 'do{2,3}g'
[root@server ~ 11:15:12]# cat words | egrep 'do{2,3}g'
doog
dooog

{m,}

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

[root@server ~ 11:15:16]# cat words | egrep 'do{2,}g'
doog
dooog
doooog

{,n}

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

[root@server ~ 11:15:29]# cat words | egrep 'do{,3}g'
dog
dg
doog
dooog

()

标记一个子表达式

[root@server ~ 11:15:40]# echo dogdog >> words
[root@server ~ 11:15:50]# echo dogdogdog >> words
[root@server ~ 11:15:55]# echo dogdogdogdog >> words
[root@server ~ 11:15:59]# cat words | egrep '(dog){2,}'

dogdog
dogdogdog
dogdogdogdog

综合案例

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

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


#解答
'^(([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])$'

grep 工具使用手册

grep 介绍

grep 是 Linux 系统中最重要的命令之一,其功能是从文本文件或管道数据流中筛选匹配的行及数据。

Linux操作文本的三大利器,简称三剑客,分别是:

  • grep:擅长过滤。
  • sed:擅长修改文本。
  • awk:擅长格式化输出。

grep 命令语法

  1. 过滤管道:command | grep [OPTION]... PATTERNS
  2. 过滤文件:grep [OPTION]... PATTERNS [FILE]...

grep 命令选项

文件准备

[root@server ~ 11:17:35]$ vim words
cat
category
acat
concatenate
cbt
c1t
cCt
c-t
c.t
dog

模式选择和解释选项

-E 选项

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

[root@server ~ 11:17:58]# cat words | grep -E '(dog){3}'

dogdogdog
dogdogdogdog
-e 选项

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

[root@server ~ 13:50:06]# cat words | egrep 'cat|dog'
cat
category
acat
concatenate
dog
hello cat kitty
dogdog
dogdogdog
dogdogdogdog
-f 选项

从文件读取多个 PATTERNS

[root@server ~ 13:50:37]# echo -e 'cat\ndog' > pattens_file
[root@server ~ 13:51:03]# cat pattens_file
cat
dog
[root@server ~ 13:51:10]# cat words | grep -f pattens_file
cat
category
acat
concatenate
dog
hello cat kitty
dogdog
dogdogdog
dogdogdogdog
-i 选项

忽略大小写匹配。

[root@server ~ 13:51:28]# cat words | grep -i 'cBt'
cbt
-w 选项

匹配整个单词

[root@server ~ 13:51:47]# cat words | grep -w 'cat'
cat
hello cat kitty
-x 选项

匹配整行

[root@server ~ 13:52:16]# cat words | grep -x 'cat'
cat

输出控制选项

-v 选项

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

[root@server ~ 13:52:36]# cat words | egrep -v '^d|^c'
acat
hello cat kitty

# 不看注释行和空白行
[root@server ~ 13:53:14]# egrep -v '^\s*# |^$' /etc/profile
-m 选项

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

[root@server ~ 13:54:13]# cat words |grep 'dog'
dog
dogdog
dogdogdog
dogdogdogdog

[root@server ~ 13:54:24]# cat words | grep -m2 'dog'
dog
dogdog
-c 选项

显示匹配到项目的数量。

[root@server ~ 13:54:40]# cat words |grep -c 'dog'
4
-b 选项

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

[root@server ~ 13:55:01]# head -5 words
cat
category
acat
concatenate
cbt


[root@server ~ 13:55:11]# cat words |grep -b 'cat'
0:cat
4:category
13:acat
18:concatenate
54:hello cat kitty
-n 选项

显示匹配项目的行号。

[root@server ~ 13:55:24]# cat words |grep -n 'cat'
1:cat
2:category
3:acat
4:concatenate
11:hello cat kitty
-o 选项

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

[root@server ~ 13:55:32]# cat words |egrep '(dog){3}'
dogdogdog
dogdogdogdog

[root@server ~ 13:56:01]# cat words |egrep -o '(dog){3}'
dogdogdog
dogdogdog
-q 选项

不显示任何正常输出。一般用于脚本判定文件中是否包含特定内容。

通过特殊变量 $? 查看是否匹配到内容。

# 找到的情况
[root@server ~ 13:56:19]# cat words |egrep -q '(dog){3}'
[root@server ~ 13:57:16]# echo $?
0

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

查找文件选项

-r -R 选项
  • -r,递归匹配目录。
  • -R,递归匹配目录,跟随软链接。
[root@server ~ 13:58:24]# grep -r '^SELINUX=' -s /etc
/etc/selinux/config:SELINUX=disabled
-h 和 -H 选项
  • -h,不显示匹配项目所在文件的文件名。
  • -H,显示匹配项目所在文件的文件名,默认情况使用该选项。
[root@server ~ 14:14:17]# grep -r '^SELINUX=' -h /etc
SELINUX=disabled

[root@server ~ 14:14:47]# grep -r '^SELINUX=' -H /etc
/etc/selinux/config:SELINUX=disabled
-l 和 -L 选项
  • -l,对目录匹配时,只显示那些 包含匹配模式的文件的名称
  • -L,对目录匹配时,只显示那些 包含匹配模式的文件的名称
[root@server ~ 14:14:51]# grep -r '^SELINUX=' -l /etc
/etc/selinux/config

[root@server ~ 14:15:04]# grep -r '^SELINUX=' -L /etc
/etc/fstab
/etc/crypttab
/etc/resolv.conf
/etc/grub.d/00_header
/etc/grub.d/01_users
/etc/grub.d/10_linux
......

输出内容控制选项

-B 选项

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

[root@server ~ 14:15:26]# ip addr | grep '10.1.8.10' -B2
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:1d:17:4e brd ff:ff:ff:ff:ff:ff
    inet 10.1.8.10/24 brd 10.1.8.255 scope global noprefixroute ens33
-A 选项

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

[root@server ~ 14:15:33]# 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:1d:17:4e brd ff:ff:ff:ff:ff:ff
    inet 10.1.8.10/24 brd 10.1.8.255 scope global noprefixroute ens33
-C 选项

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

[root@server ~ 14:15:57]# ip addr | grep '10.1.8.10' -C2
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:1d:17:4e brd ff:ff:ff:ff:ff:ff
    inet 10.1.8.10/24 brd 10.1.8.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::73ae:4add:7559:5f94/64 scope link noprefixroute 

sed 工具使用手册

sed 介绍

sed,英文全称 stream editor ,是一种非交互式的流编辑器,能够实现对文本非交互式的处理,功能很强大。

sed 是一个 70 后,诞生于 1973 - 1974 年间,具体时间未知。而出生地则是鼎鼎大名的 贝尔实验室

sed 是 麦克马洪 ( McMahon ) 老爷子在 贝尔实验室 时开发出来的。

sed 的诞生使并不是那么的神秘,它的诞生只不过是 麦克马洪 ( McMahon ) 老爷子想写一个 行编辑器,谁知写着写着就写成了 sed 的样子。

其实,在 sed 之前还有一个更古老的行编辑器,名字叫做 ed 编辑器。大概是 麦克马洪 ( McMahon ) 老爷子觉得 ed 编辑器不好用吧,顺手重新构架和编写。

Linux操作文本的三大利器,简称三剑客,分别是:

  • grep:擅长过滤。
  • sed:擅长修改文本。
  • awk:擅长格式化输出。

sed 与 awk 并称为 Linux/Unix 世界的两大王牌文字处理器:

  • sed 侧重点是替换。
  • awk 侧重点是分割和重新合成。

sed 工作流程

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

img

  1. 读取行

sed 从输入流 (文件、管道、标准输入流)中读取 一行 并存储在名叫 pattern space 的内部空间中。

sed 是行文字处理器。每次只会读取一行。

sed 内部会有一个计数器,记录着当前已经处理多少行,也就是当前行的行号。

  1. 执行

按照 sed 命令定义的顺序依次应用于刚刚读取的 一行 数据。

默认情况下,sed 一行一行的处理所有的输入数据。但如果我们指定了行号,则只会处理指定的行。

  1. 显示

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

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

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 程序执行前,模式 patternhold space 空间都是空的。
  • 如果我们没有传递任何输入文件,sed 默认会从 标准输入 中读取数据。
  • sed 可以指定只处理输入数据中的行范围。默认情况下是全部行,因此会依次处理每一行。

sed 命令语法

sed 帮助

[root@server ~ 14:25:26]$ sed --help
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

  -n, --quiet, --silent
                 suppress automatic printing of pattern space
  -e script, --expression=script
                 add the script to the commands to be executed
  -f script-file, --file=script-file
                 add the contents of script-file to the commands to be executed
  --follow-symlinks
                 follow symlinks when processing in place
  -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
                 specify the desired line-wrap length for the `l' command
  --posix
                 disable all GNU extensions.
  -r, --regexp-extended
                 use extended regular expressions in the script.
  -s, --separate
                 consider files as separate rather than as a single continuous
                 long stream.
  -u, --unspaceed
                 load minimal amounts of data from the input files and flush
                 the output spaces more often
  -z, --null-data
                 separate lines by NUL characters
  --help
                 display this help and exit
  --version
                 output version information and exit

If no -e, --expression, -f, or --file option is given, then the first
non-option argument is taken as the sed script to interpret.  All
remaining arguments are names of input files; if no input files are
specified, then the standard input is read.

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.
 -n, --quiet, --silent    取消自动打印模式空间
 -e 脚本, --expression=脚本   添加“脚本”到程序的运行列表
 -f 脚本文件, --file=脚本文件  添加“脚本文件”到程序的运行列表
 --follow-symlinks    直接修改文件时跟随软链接
 -i[扩展名], --in-place[=扩展名]    直接修改文件(如果指定扩展名就备份文件)
 -l N, --line-length=N   指定“l”命令的换行期望长度
 --posix  关闭所有 GNU 扩展
 -r, --regexp-extended  在脚本中使用扩展正则表达式
 -s, --separate  将输入文件视为各个独立的文件而不是一个长的连续输入
 -u, --unspaceed  从输入文件读取最少的数据,更频繁的刷新输出
 --help     打印帮助并退出
 --version  输出版本信息并退出
 -a ∶新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)-c ∶取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
 -d ∶删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
 -i ∶插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行)-p ∶列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作~
 -s ∶取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法

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

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

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

  1. sed 命令。
  2. [option] 命令行选项,用于改变 sed 的工作流程。
  3. [sed-command] 是具体的 sed 命令。
  4. [input-file] 输入数据,如果不指定,则默认从标准输入中读取。

示例1:模拟cat命令打印文件内容

[root@server ~ 14:46:34]# cat > data.txt <<'EOF'
> I am studing sed
> I am www.laoma.cloud
> I am a Superman
> I am so handsome
> EOF

[root@server ~ 15:00:37]# sed "data.txt
> I am studing sed
> I am www.laoma.cloud
> I am a Superman
> I am so handsome

对照着 sed 命令的语法格式:

  • 这里未使用 option
  • '' ,对应着 [sed-command] 为具体的 sed 语句。
  • data.txt ,对应着 [input-file],用于提供输入数据。

示例2:从标准输入中读取数据

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

[root@server ~ 15:01:09]# sed ''
#输入任意字符串回车
hello
hello
hi
hi
# 输出hello world
hello world
# 按ctrl+d推出

-e 选项

从命令行读取sed命令,我们需要将 sed 命令使用单引号 ( '' ) 引起来。

# 打印data.txt文件内容
[root@server ~ 15:01:51]# sed -e '' data.txt
I am studing sed
I am www.laoma.cloud
I am a Superman
I am so handsome
# 如果只有一个命令,-e选项可以省略
[root@server ~ 15:01:58]# sed  '' data.txt
I am studing sed
I am www.laoma.cloud
I am a Superman
I am so handsome

# -e 选项可以多次使用,1d是作用是删除第一行
[root@server ~ 15:02:33]# sed -e '1d' -e '2d' -e '5d' data.txt
I am a Superman
I am so handsome

# 因为不存在第五行,所以也就没删除的效果

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

-f 选项

sed 还支持把所有 sed 命令保存在一个普通的文本文件里,然后通过 -f 选项来运行这个文件。

当把 sed 存储在文件中时,需要注意 每一个 sed 命令独自成一行

文件的作用仅仅用于存储命令而已,因此存储 sed 命令的文件并没有任何特殊,可以是一个 .txt 文本文件。

[root@server ~ 15:03:23]# echo -e "1d\n2d\n5d" > scripts
[root@server ~ 15:03:49]# cat scripts 
1d
2d
5d

[root@server ~ 15:03:53]# sed -f scripts data.txt 
I am a Superman
I am so handsome

-n 选项

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

# 以下命令没有任何输出
[root@server ~ 15:04:04]# sed -n '' data.txt

# 打印第一行记录
[root@server ~ 15:04:24]# sed -n '1p' data.txt
I am studing sed

sed 行寻址

作用

通过行寻址匹配要处理的输入流。

语法

这里以打印命令p为例。

语法:[address1[,address2]]p

  • address1address2 分别是 起始地址结束地址,可以是 行号模式字符串
  • address1address2 都是可选参数,可以都不填,这时候就是打印所有行,从文件的开头到文件结束。
  • 如果存在一个,那么就是打印 单行。也就是只打印 address1 指定的那行。
  • p 命令仅从 模式缓冲区 中打印行,也就是该行不会发送到输出流,原始文件保持不变。

示例文件

[root@server ~ 15:04:32]# echo 'This is 1    
> This is 2    
> This is 3
> This is 4
> This is 5 ' > test

演示

示例1: 打印所有行

# 打印所有行
[root@server ~ 15:05:49]# cat test |sed ''
This is 1    
This is 2    
This is 3
This is 4
This is 5 

# sed 默认打印模式缓冲区中所有内容。

# 等效于
[root@server ~ 15:06:00]# cat test |sed -n 'p'
This is 1    
This is 2    
This is 3
This is 4
This is 5 
# -n 关闭sed打印模式缓冲区中所有内容。
# p命令,明确打印输出模式缓冲区中所有内容。

示例2: 打印特定行

# 打印第1行
[root@server ~ 15:06:09]# cat test |sed -n '1p'

# 输出结果
This is 1

# 打印第最后一行
[root@server ~ 15:06:13]# cat test |sed -n '$p'
# 输出结果
This is 5

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

[root@server ~ 15:06:17]# cat test |sed -n '1,3p'

# 输出结果
This is 1
This is 2    
This is 3

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

[root@server ~ 15:06:22]# cat test |sed -n '3,$p'

# 输出结果   
This is 3
This is 4
This is 5

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

[root@server ~ 15:06:27]# cat test |sed -n '2,+2p'

# 输出结果
This is 2 
This is 3
This is 4

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

[root@server ~ 15:06:34]# cat test |sed -n '1~2p'

# 输出结果
This is 1    
This is 3
This is 5

sed 模式寻址

sed 除了可以从行号来选择行,s还支持模式查找指定的行。

  • 模式 可以是一个普通的字符串或者一个正则表达式。
  • 模式 的语法和行寻址的语法类似,只是把行号换成了 模式 匹配。

例如,输出匹配指定模式的行,语法格式如下:

/pattern/

示例文件

[root@server ~ 15:06:40]# 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的行

[root@server ~ 15:07:07]# 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开头的行

[root@server ~ 15:07:29]# 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开头的行到第三行

[root@server ~ 15:07:54]# 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开头的行到最后一行

[root@server ~ 15:08:05]# cat test |sed -n '/^root/,$p'

sed 子命令

打印

作用
  • p,打印模式空间所有记录。
  • P,打印模式空间第一行记录。
语法

格式:[address1[,address2]]p

  • address1address2 分别是 起始地址结束地址,可以是 行号模式字符串
  • address1address2 都是可选参数,可以都不填,这时候就是打印所有行,从文件的开头到文件结束。
  • 如果存在一个,那么就是打印 单行。也就是只打印 address1 指定的那行。
  • p 命令仅从 模式缓冲区 中打印行,也就是该行不会发送到输出流,原始文件保持不变。

读取下一行

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

说明:

  • 读取 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. N,追加下一行到当前行后面,组成一个新行来处理。
  2. s/\n/==/,将新行中 \n 换行符替换成==,末尾的换行符不替换。

替换

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

[root@server ~ 15:08:30]# sed 's/root/tankzhang/' test |grep tankzhang
tankzhang:x:0:0:root:/root:/bin/bash

关闭 SELinux

[root@server ~ 15:11:08]# sed -i 's/^SELINUX=.*/SELINUX=disabled/g' config

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

[root@server ~ 15:11:36]# sed 's/root/tankzhang/g' test |grep tankzhang
tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash

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

[root@server ~ 15:11:50]# sed -n 's/root/tankzhang/p' test
tankzhang:x:0:0:root:/root:/bin/bash

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

[root@server ~ 15:11:50]# sed -n 's/root/tankzhang/p' test
tankzhang:x:0:0:root:/root:/bin/bash

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

[root@server ~ 15:12:10]# sed -ne '2,8s/^zhang/ying/gp' test
yingy:x:1000:100:,,,:/home/zhangy:/bin/bash

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

[root@server ~ 15:13:10]# 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: 自定义替换分隔符为 #

[root@server ~ 15:14:00]# sed -n 's#root#hello#gp' test
hello:x:0:0:hello:/hello:/bin/bash

分隔符 ; 和 -e 选项

需要执行多个sed处理命令时,用分号分开,或者使用 -e 选项。

示例:

  • 在第2行到第8行之间,替换以zhang开头的行,用ying来替换
  • 在第5行到第10行之间,用goodbay来替换dbus,并显示替换的行
[root@server ~ 15:14:15]# 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

[root@server ~ 15:15:02]#  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) 在匹配行下面插入新行
[root@server ~ 15:15:09]# sed '/root/a====aaaa===='test
root:x:0:0:root:/root:/bin/bash
====aaaa====
bin:x:1:1:bin:/bin:/bin/false
......
i(insert) 在匹配行上面插入新行
[root@server ~ 15:15:56]# sed '/root/i====iiii====' test
====iiii====
root:x:0:0:root:/root:/bin/bash
.....

删除

作用
  • d,删除模式空间所有记录。
  • D,删除模式空间第一行记录。
语法

d 格式:[address1[,address2]]d

D 格式:[address1[,address2]]D

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

d 删除 示例

示例1: 删除1-14行

[root@server ~ 19:14:02]# sed -e '1,14d' test
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po

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

[root@server ~ 19:14:05]# 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的行,别忘了加\

[root@server ~ 19:14:17]# sed -re '/(false|bash)/d' test
policykit:x:102:1005:Po

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

[root@server ~ 19:14:27]# sed -e '/root/,/^test/d' test
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po

更改

整行替换。

示例:root开头行替换成hello

[root@server ~ 19:14:35]# sed '/^root/chello' test
hello
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
......

# 等效下面命令
[root@server ~ 19:14:55]# sed 's/^root.*/hello/' test

awk 工具使用手册

awk 介绍

awk 是一个强大的文本分析工具。

awk 是取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

awk 更像一门编程语言,他可以自定义变量,有条件语句,有循环,有数组,有正则,有函数等。

awk 按行读取数据,根据给出的条件进行查找,并在找出来的行中进行操作。

awk 命令

awk 命令格式

awk [options] 'script' file(s) 
awk [options] -f scriptfile file(s) 
  1. script,定义如何处理数据。
  2. file,是 awk 处理的数据来源,awk 也可以来自其它命令的输出。
  3. -f scriptfile 从脚本文件中读取awk命令,每行都是一个独立的script

script 格式如下:

BEGIN { action }
pattern { action }
END { action }

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

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

BEGIN { action }pattern { action }END { action }都是可选项目。

awk 工作流

image-20230402163532397

  • 第一步执行 BEGIN { commands } 语句块中的语句。

在awk从输入输出流中读取行之前执行,通常在BEGIN语句块中执行如变量初始化,打印输出表头等操作。

  • 第二步:**从文件或标准输入中读取一行,然后执行 pattern { commands }语句块。**它逐行读取数据,从第一行到最后一行重复这个过程,直到读取完所有行。

pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行。

{} 类似一个循环体,会对文件中的每一行进行迭代,通常将变量初始化语句放在BEGIN语句块中,将打印结果等语句放在END语句块中。

  • 第三步当读至输入流末尾时,执行 END { command }语句块。

在awk从输入流中读取完所有的行之后执行,比如打印所有行的分析结果,它也是一个可选语句块。

awk 示例

示例文件

[root@server ~ 19:15:05]# cat << 'EOF' > employee.txt 
> 1)  张三  技术部  23
> 2)  李四  人力部  22
> 3)  王五  行政部  23
> 4)  赵六  技术部  24
> 5)  朱七  客服部  23
> EOF

示例1: 打印雇员信息。

[root@server ~ 19:15:30]# awk '{ print }' employee.txt 
1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23

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

[root@server ~ 19:15:40]# cat commands.awk 
{ print }
[root@server ~ 19:15:55]# awk -f commands.awk employee.txt 
1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23

示例3: 输出特定隔行。

[root@server ~ 19:16:12]# awk '/张三/ { print }' employee.txt 
1)  张三  技术部  23
# 等同于
[root@server ~ 19:16:27]# awk '/张三/' employee.txt 
1)  张三  技术部  23

示例5: 输出总长度大于 10 的行。

AWK 提供了一个内建的函数 **length(arg)∗∗用于返回字符串‘arg)** 用于返回字符串 `arg)用于返回字符串arg` 的总长度。

如果要获取某行的总长度,可以使用下面的语法:length($0)

同样的,如果要获取某列/字段的总长度,可以使用语法: length($n)

如果要判断某行的字符是否大于/小于/等于 N ,可以使用下面的语法:length($0) > N

[root@server ~ 19:17:14]# awk 'length($0)>10 { print $0 }' employee.txt

因为所有的行的总长度都大于 18,因此输出结果如下:

1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23

awk 综合示例

雇员信息表如下:

[root@server ~ 19:17:15]#  cat employee.txt 
1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23

示例文件结构:

  1. 每个雇员独占一行
  2. 每个雇员都包括以下字段:序号,名字,部门,年龄
  3. 每一行的多个字段之间使用空白作为分隔符,空白分隔符一般是空格 ( ) 或者制表符 \t
问题

我们想要获得以下输入结果

序号 姓名  部门   年龄
-------------------
1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23
-------------------
分析

从上面的结果中可以看出,整个输出结果分为三大部分

  1. 表头

```序号 姓名 部门 年龄


```

  1. 数据

每个雇员一样,且有着以下的结构

1) 张三 技术部 23 2) 李四 人力部 22 3) 王五 行政部 23 4) 赵六 技术部 24 5) 朱七 客服部 23
  1. 表尾

```


```

根据我们刚刚学到的知识,AWK 程序结构分为三大部分,BEGIN 和 END 只会执行一次,看起来刚好可以用来输出表头,而 AWK 主体代码,是针对每一行执行的,因此,刚好可以用来输出数据。

解答
表头

为了输入表头,我们可以使用下面的 Shell 语句

[root@server ~ 19:18:20]# awk '
> BEGIN { printf "序号\t名字\t部门\t年龄\n-------------------\n" }'

因为表头部分不需要处理输入文件,也不需要处理输入文件中的每一行,所以 AWK 主体代码都是可以忽略的,甚至包括输入文件都是可以忽略的。

运行以上代码,输出结果如下:

序号  名字  部门  年龄
-------------------
数据

对比想要的结果和输入的文件,可以看出输出结果并并没有对每一行做特殊处理,直接显示就好

因此,只需要在 BEGIN 块后面直接添加 { print } ,添加完代码如下:

[laoma@shell ~]$ cat employee.txt | awk '
BEGIN { printf "序号\t名字\t部门\t年龄\n-------------------\n" } 
{ print }
END {printf "-------------------\n"}'

print 用命令于输出当前行。

运行以上代码,输出结果如下:

序号  名字  部门  年龄
-------------------
1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23
-------------------
-F 选项

**作用:**用于定义awk程序的分隔符。awk程序的分隔符,是用于分割同一行数据的分割符号。默认分隔符是:空格。

语法:-F fs 或者 --field-separator=fs

**示例:**打印用户名和家目录

[root@server ~ 19:18:26]# head -n1 /etc/passwd
root:x:0:0:root:/root:/bin/bash

[root@server ~ 19:19:20]# head -n1 /etc/passwd | awk -F : '{ print $1" "$6 }'
root /root
-v 选项

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

  1. 定义内部变量接收外部变量。

```bash [laoma@shell ~]$ var1=“aaa” [laoma@shell ~]$ var2=“bbb” [laoma@shell ~]$ echo | awk ‘{ print v1,v2 }’ v1=var1v2=var1 v2=var1v2=var2 aaa bbb

# 输入来自文件时 [laoma@shell ~]$ awk ‘{ print v1,v2 }’ v1=var1v2=var1 v2=var1v2=var2 /etc/hostname aaa bbb ```

-p 选项

**作用:**用于将当前的 awk 程序代码格式化并且输出到 file 文件中。

格式:--profile[=file] 或者 -p[file]

awk默认导出的 awk 程序代码格式化代码到 awkvars 文件中。

示例:

[root@server ~ 19:20:12]# awk --profile '
> BEGIN { printf"---|Header|--\n" }
> { print } 
> END { printf"---|Footer|---\n" }' employee.txt > /dev/null 

运行上面的 awk 程序,awkprof.out 内容如下:

    # gawk profile, created Wed Aug 20 11:36:46 2025

    # BEGIN block(s)

    BEGIN {
        printf "---|Header|--\n"
    }

    # Rule(s)

    {
        print $0
    }

    # END block(s)

    END {
        printf "---|Footer|---\n"
    }

awk 内置变量

在上述的示例中,我们使用了很多 awk 内置变量。

我们可以使用 -d 选项,导出awk内置的预定义变量到 file 文件中。

格式:--dump-variables[=file] 或者-d[file]

awk默认导出的内置的预定义变量保存在文件 awkvars 文件中。

示例:

[root@server ~ 19:20:27]# awk -d ''
[root@server ~ 19:20:50]# 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 完整的输入记录。

NF 变量

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

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

[root@server ~ 19:20:54]# echo -e "一 二\n一 二 三\n一 二 三 四" | awk '{ print $0 "\t",NF }'

运行以上代码,输出结果如下:

一 二  2
一 二 三    3
一 二 三 四  4

变量 NF 还可以用于条件判断。

例如,下面的命令输出了哪些字段/列大于 2 的行。

[root@server ~ 19:21:08]# echo -e "一 二\n一 二 三\n一 二 三 四" | awk 'NF > 2'

运行以上代码,输出结果如下:

一 二 三
一 二 三 四

NR 变量

变量 NRNumber of Record 的缩写,用于表示当前行的行号,也就是处理到第几行。行编号从 1 开始。

下面的代码,用于在每一行数据的前面输出当前的行号

[root@server ~ 19:21:17]# echo -e "一 二\n一 二 三\n一 二 三 四" | awk '{ print NR". "$0 }'

运行以上代码,输出结果如下:

1. 一 二
2. 一 二 三
3. 一 二 三 四

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

[root@server ~ 19:21:27]# echo -e "一 二\n一 二 三\n一 二 三 四" |  awk 'NR < 3'

运行以上代码,输出结果如下:

一 二
一 二 三

$N

对于 AWK 来说,默认的分割符是空白符号,包括 “\t” 和空格 " "。当 AWK 使用分割符对每一行进行分割后,会对每一列/字段进行编号:

  • $1 $2 $3 ...,分别代表第1列,第2列,第3列…
  • $0 ,代表一整行

示例1:

[root@server ~ 19:21:44]# head -n1 /etc/passwd
root:x:0:0:root:/root:/bin/bash

[root@server ~ 19:21:57]#  head -n1 /etc/passwd |awk  '{ print $0 }'
root:x:0:0:root:/root:/bin/bash

[root@server ~ 19:22:19]# head -n1 /etc/passwd |awk -F : '{ print $1" "$6 }'
root /root

示例2: 统计 /usr/share/doc 目录下文件size最大的前10个,并显示文件size。

[root@server ~ 19:22:28]# sudo find /usr/share/doc -type f  -ls | awk '{print $7,$11}' | sort -nr | head
725773 /usr/share/doc/rpm-4.11.3/ChangeLog.bz2
588023 /usr/share/doc/rsyslog-8.24.0/ChangeLog
548330 /usr/share/doc/xz-5.2.2/ChangeLog
521349 /usr/share/doc/yum-3.4.3/ChangeLog
509135 /usr/share/doc/grub2-common-2.02/grub.html
486761 /usr/share/doc/man-db-2.6.3/ChangeLog
412827 /usr/share/doc/tar-1.26/ChangeLog
411052 /usr/share/doc/findutils-4.5.11/ChangeLog
379303 /usr/share/doc/glib2-2.56.1/NEWS
360877 /usr/share/doc/parted-3.1/ChangeLog

# 如何让文件的单位使用human size显示?
[root@server ~ 19:22:37]# sudo find /usr/share/doc -type f  -ls | awk '{print $7,$11}' | sort -nr | head |awk '{print $2}' | xargs ls -lh
-rw-r--r--. 1 root root 402K 22 2013 /usr/share/doc/findutils-4.5.11/ChangeLog
-rw-r--r--. 1 root root 371K 47 2018 /usr/share/doc/glib2-2.56.1/NEWS
-rw-r--r--. 1 root root 498K 520 2022 /usr/share/doc/grub2-common-2.02/grub.html
-rw-r--r--. 1 root root 476K 918 2012 /usr/share/doc/man-db-2.6.3/ChangeLog
-rw-r--r--. 1 root root 353K 33 2012 /usr/share/doc/parted-3.1/ChangeLog
-rw-r--r--. 1 root root 709K 95 2014 /usr/share/doc/rpm-4.11.3/ChangeLog.bz2
-rw-r--r--. 1 root root 575K 110 2017 /usr/share/doc/rsyslog-8.24.0/ChangeLog
-rw-r--r--. 1 root root 404K 312 2011 /usr/share/doc/tar-1.26/ChangeLog
-rw-r--r--. 1 root root 536K 929 2015 /usr/share/doc/xz-5.2.2/ChangeLog
-rw-r--r--. 1 root root 510K 629 2011 /usr/share/doc/yum-3.4.3/ChangeLog

awk 运算符

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

赋值运算符

[root@server ~ 19:22:48]# awk 'BEGIN { x=5;x+=2;print "x="x }'
x=7
[root@server ~ 19:23:03]# awk 'BEGIN { x=5;x-=2;print "x="x }'
x=3
[root@server ~ 19:23:09]# awk 'BEGIN { x=5;x*=2;print "x="x }'
x=10
[root@server ~ 19:23:13]# awk 'BEGIN { x=5;x/=2;print "x="x }'
x=2.5
[root@server ~ 19:23:17]# awk 'BEGIN { x=5;x%=2;print "x="x }'
x=1
[root@server ~ 19:23:21]# awk 'BEGIN { x=5;x^=2;print "x="x }'
x=25
[root@server ~ 19:23:25]# awk 'BEGIN { x=5;x**=2;print "x="x }'
x=25

算数运算符

[root@server ~ 19:24:08]# [root@server ~ 19:22:48]# awk 'BEGIN { x=5;x+=2;print "x="x }'
[root@server ~ 19:24:24]# x=7
[root@server ~ 19:24:24]# [root@server ~ 19:23:03]# awk 'BEGIN { x=5;x-=2;print "x="x }'
[root@server ~ 19:24:24]# x=3
[root@server ~ 19:24:24]# [root@server ~ 19:23:09]# awk 'BEGIN { x=5;x*=2;print "x="x }'
[root@server ~ 19:24:24]# x=10
[root@server ~ 19:24:24]# [root@server ~ 19:23:13]# awk 'BEGIN { x=5;x/=2;print "x="x }'
[root@server ~ 19:24:24]# x=2.5
[root@server ~ 19:24:24]# [root@server ~ 19:23:17]# awk 'BEGIN { x=5;x%=2;print "x="x }'
[root@server ~ 19:24:24]# x=1
[root@server ~ 19:24:24]# [root@server ~ 19:23:21]# awk 'BEGIN { x=5;x^=2;print "x="x }'
[root@server ~ 19:24:24]# x=25
[root@server ~ 19:24:24]# [root@server ~ 19:23:25]# awk 'BEGIN { x=5;x**=2;print "x="x }'
[root@server ~ 19:24:24]# x=25

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐