Linux三剑客实例详解
# Linux三剑客实例详解「grep、sed 、awk」
# 三剑客的前言
# 简介
Linux 操作文本的三大利器分别是grep、sed 、awk,简称三剑客。
大师兄 awk:最擅长取列;二师兄 sed:最擅长取行;三师兄 grep:最擅长过滤。
# 概述
三者的功能都是处理文本,但侧重点各不相同,其中属 awk
功能最强大,但也最复杂。grep
更适合单纯的查找或匹配文本,sed
更适合编辑匹配到的文本,awk
更适合格式化文本,对文本进行较复杂格式处理。
简单概括:
grep:数据查找定位
awk:数据切片
sed:数据修改
# 正则表达式
正则表达式:REGular EXPression, REGEXP。我们通过特定的字符串匹配模板,来获取到所需的内容。熟练掌握好正则表达式是使用Linux三剑客
的前提啊。
# 元字符
.
: 匹配任意单个字符;
[]
: 匹配指定范围内的任意单个字符;
[^]
:匹配指定范围外的任意单个字符;
# 字符集合
[[:digit:]]
:匹配单个数字;
[[:lower:]]
:匹配单个小写字母;
[[:upper:]]
:匹配单个大写字母;
[[:punct:]]
:匹配单个标点字符;
[[:space:]]
:匹配单个空白字符;
[[:alpha:]]
:匹配单个字母;
[[:alnum:]]
:匹配单个字母或数字;
# 匹配次数(贪婪模式)
*
:匹配其前面的字符任意次
?
:匹配其前面的字符0次或者1次
+
:匹配其前面的字符至少1次
.*
:任意长度的任意字符
# 位置锚定
^
: 锚定行首,此字符后面的任意内容必须出现在行首
$
: 锚定行尾,此字符前面的任意内容必须出现在行尾
^$
: 空白行
# Linux实际使用
由于linux系统shell解释器的特殊处理,某些元字符在linux下具有展开式等特殊含义,在实际的使用过程中我们需要添加\
进行转义。
\?
:匹配其前面的字符1次或0次;
\+
:匹配至少一次;
\{m,n\}
:匹配其前面的字符至少m次,至多n次;
\{1,\}
:匹配前面的字符至少1次;
\{0,3\}
:匹配前面的字符0次至3次均可;
备注:至少0次,必须要显示的写出来;
\<或\b
:锚定词首,其后面的任意字符必须作为单词首部出现
\>或\b
:锚定词尾,其前面的任意字符必须作为单词的尾部出现
# 分组与后向引用
\(\)
\(ab\)*
\1
:引用第1个左括号以及与之对应的括号所包括的所有内容;
\2
:引用第2个左括号以及与之对应的括号所包括的所有内容,以此类推;
# 拓展正则表达式
可以看到标准正则表达的使用过程中,许多符号都需要转义,这在工作中带来了一定的不便,因此扩展的正则表达式便出现了。 "用egrep"
# 字符匹配:
.
:匹配单个字符;
[abc]
:包含abc任意一个字符
[^abc]
:不包含abc任意一个字符
# 次数匹配(不用再转义):
*
:匹配前一个字符任意次;
?
:匹配其前面的字符1次或0次;
+
:匹配其前面的字符至少1次;
{m,n}
:匹配其前面的字符至少m次,至多n次;
# 位置锚定:
对比使用方式:^
和 $
这里要注意的是对于词首定位和词尾定位,分别是\<
和 \>
,依然需要加上反斜杠;
# 分组(不用再转义):
()
:分组
\1
, \2
, \3
:分别对应第n个括号所匹配的内容;
# 或运算
|
: 可以同时取并集;
注意:C|cat表示的是C或cat(表示的是整个部分)
可以看到,使用扩展的正则表达式可以省略很多的转义符号,这尤其在写sed语句时极大的提高了代码的可读性。建议优先使用扩展的正则表达式。
# grep命令
# grep相关命令
grep命令家族由grep, egrep, fgrep 三个子命令组成,适用于不同的场景。具体如下:
# 命令描述
grep 原生的grep命令,使用“标准正则表达式”作为匹配标准。
egrep 扩展的grep命令,相当于$(grep -E)
,使用“扩展正则表达式”作为匹配标准。
fgrep 简化版的grep命令,不支持正则表达式,但搜索速度快,系统资源使用率低。
# 使用方法
语法 grep [options] PATTERN [FILE...]
options部分
-n
:显示行号
-w
:被匹配的文本只能是单词,而不能是单词中的某一部分,如文本中有liker,而我搜寻的只是like,就可以使用-w选项来避免匹配liker
-c
:显示总共有多少行被匹配到了,而不是显示被匹配到的内容,注意如果同时使用-cv选项是显示有多少行没有被匹配到。
-A
n:显示匹配到的字符串所在的行及其后n行,after
-B
n:显示匹配到的字符串所在的行及其前n行,before
-C
n:显示匹配到的字符串所在的行及其前后各n行,context-i
:忽略大小写
--color
:高亮匹配上的字符串
-v
: 显示没有被模式匹配到的行
-o
:只显示被模式匹配到的字符串
-E
:使用扩展的正则表达式,egrep=grep -E
PATTERN部分 以字符串的方式给定匹配模板,可以使用普通字符串以及正则表达式(标准&扩展)。
FILE部分 需要查找内容的文件。
# 示例数据文件
请将以下数据剪切粘贴到一个名为 “sampler.log” 的文件中:
1. boot
2. book
3. booze
4. machine
5. boots
6. bungie
7. bark
8. aardvark
9. broken$tuff
10. robots
# grep最简单的例子
- 在本例中,grep 将遍历文件 “sampler.log” 的每一行,并打印出其中的每一行 包含单词“boo”:
$ grep "boo" sampler.log
boot
book
booze
boots
- 但是如果你操作的是大型文件,就会出现这种情况:如果这些行标识了文件中的
哪一行
,它们是什么,可能对你更有用,如果需要在编辑器中打开文件,那么可以更容易地跟踪特定字符串做一些改变。 这时候可以通过添加-n参数来实现
:
这产生了一个更有用的结果,解释了哪些行与搜索字符串匹配:
$ grep -n "boo" sampler.log
1:boot
2:book
3:booze
5:boots
- 另一个有趣的
参数是 -v
,它会打印出相反的结果
。换句话说,grep 将打印所有与搜索字符串不匹配的行
,而不是打印与之匹配的行。
在下列情况下,grep 将打印不包含字符串 “boo” 的每一行,并显示行号,如上一个例子所示
$ grep -vn "boo" sampler.log
4:machine
6:bungie
7:bark
8:aardvark
9:broken$tuff
10:robots
c 选项
告诉grep抑制匹配行的打印
,只显示匹配行的数量
,匹配查询的行。 例如,下面将打印数字4,因为有4个在sampler.log
中出现 “boo”。
$ grep -c "boo" sampler.log
4
l 选项
只打印查询中具有与搜索匹配行的文件的文件名字符串
。 如果你想在多个文件中搜索相同的字符串,这将非常有用。像这样:
$ grep -l "boo" *
sampler.log
- 对于搜索非代码文件,一个更
有用的选项是-i
,忽略大小写
。这个选项将处理在匹配搜索字符串时,大小写相等。 在下面的例子中,即使搜索字符串是大写的,包含“boo”的行也会被打印出来。
$ grep -i "BOO" sampler.log
boot
book
booze
boots
x 选项
只精确匹配。换句话说,以下命令搜索没有结果,因为没有一行只包含"boo"
$ grep -x "boo" sampler.log
- 最后,
-A 允许你指定额外的上下文件行
,这样就得到了搜索字符串额外行,例如
$ grep -A2 "mach" sampler.log
machine
boots
bungie
# grep使用正则表达式
# 基本匹配:
正则表达式其实就是在执行搜索时的格式,它由一些字母和数字组合而成。 例如:一个正则表达式 the
,它表示一个规则:由字母t
开始,接着是h
,再接着是e
。
"the" => The fat cat sat on the mat.
# 元字符
正则表达式主要依赖于元字符。 元字符不代表他们本身的字面意思,他们都有特殊的含义。一些元字符写在方括号中的时候有一些特殊的意思。以下是一些元字符的介绍:
元字符 | 描述 | |
---|---|---|
. | 句号匹配任意单个字符除了换行符。 | |
[ ] | 字符种类。匹配方括号内的任意字符。 | |
[^ ] | 否定的字符种类。匹配除了方括号里的任意字符 | |
* | 匹配>=0个重复的在*号之前的字符。 | |
+ | 匹配>=1个重复的+号前的字符。 | |
? | 标记?之前的字符为可选. | |
{n,m} | 匹配num个大括号之前的字符或字符集 (n <= num <= m). | |
(xyz) | 字符集,匹配与 xyz 完全相等的字符串. | |
| | 或运算符,匹配符号前或后的字符. | |
\ | 转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \ | | |
^ | 从开始行开始匹配. | |
$ | 从末端开始匹配. | |
.* | 所有内容 | 搭配.* |
^$ | 空行 | 搭配^$ |
# 将例子使用如下文件:
[root@shell-centos-1 ~]# cat a.txt
The car parked in the garage.
[root@shell-centos-1 ~]# cat b.txt
A garage is a good place to park a car.
[root@shell-centos-1 ~]# cat c.txt
The fat cat sat on the concatenation.
[root@shell-centos-1 ~]# cat d.txt
The fat cat sat on the mat.
[root@shell-centos-1 ~]# cat e.txt
The number was 9.9997 but we rounded it off to 10.0.
# 点运算符 .
.
是元字符中最简单的例子。 .
匹配任意单个字符,但不匹配换行符。 例如,表达式.ar
匹配一个任意字符后面跟着是a
和r
的字符串。
[root@shell-centos-1 ~]# grep .ar a.txt
The
car par
ked in thegar
age.
# 字符集 []
[root@shell-centos-1 ~]# grep [Th] a.txt
Th
e car parked in th
e garage.
方括号的句号就表示句号。 表达式 ar[.]
匹配 ar.
字符串
[root@shell-centos-1 ~]# echo A garage is a good place to park a car. > b.txt #使用该测试文件
[root@shell-centos-1 ~]# grep ar[.] b.txt
A garage is a good place to park a c
ar.
# 否定字符集
一般来说 ^
表示一个字符串的开头,但它用在一个方括号的开头的时候,它表示这个字符集是否定的。 例如,表达式[^c]ar
匹配一个后面跟着ar
的除了c
的任意字符。
[root@shell-centos-1 ~]# grep [^c]ar a.txt
The car
par
ked in thegar
age.
# 重复次数
后面跟着元字符 +
,*
or ?
的,用来指定匹配子模式的次数。 这些元字符在不同的情况下有着不同的意思。
# *
号
*
号匹配 在*
之前的字符出现大于等于0
次。 例如,表达式 a*
匹配0或更多个以a开头的字符。表达式[a-z]*
匹配一个行中所有以小写字母开头的字符串。
[root@shell-centos-1 ~]# grep "[a-z]*" a.txt
T
he car parked in the garage
.
*
字符和.
字符搭配可以匹配所有的字符.*
。 *
和表示匹配空格的符号\s
连起来用,如表达式\s*cat\s*
匹配0或更多个空格开头和0或更多个空格结尾的cat字符串。
[root@shell-centos-1 ~]# echo The fat cat sat on the concatenation. > c.txt #这里使用该测试文件
[root@shell-centos-1 ~]# grep "\s*cat\s*" c.txt
The fat
cat
sat on the concat
enation.
# +
号
+
号匹配+
号之前的字符出现 >=1 次。 例如表达式c.+t
匹配以首字母c
开头以t
结尾,中间跟着至少一个字符的字符串。
[root@shell-centos-1 ~]# echo The fat cat sat on the mat. > d.txt #这里使用该测试文件
[root@shell-centos-1 ~]# egrep "c.+t" d.txt
The fat
cat sat on the mat
.
# ?
号
在正则表达式中元字符 ?
标记在符号前面的字符为可选,即出现 0 或 1 次。 例如,表达式 [T]?he
匹配字符串 he
和 The
。
[root@shell-centos-1 ~]# grep "[T]\?he" a.txt
The
car parked inthe
garage.
# {}
号
在正则表达式中 {}
是一个量词,常用来限定一个或一组字符可以重复出现的次数。 例如, 表达式 [0-9]{2,3}
匹配最少 2 位最多 3 位 0~9 的数字。
[root@shell-centos-1 ~]# echo The number was 9.9997 but we rounded it off to 10.0. > e.txt #使用该测试文件
[root@shell-centos-1 ~]# egrep "[0-9]{2,3}" e.txt
The number was 9.
999
7 but we rounded it off to10
.0.
我们可以省略第二个参数。 例如,[0-9]{2,}
匹配至少两位 0~9 的数字。
[root@shell-centos-1 ~]# egrep "[0-9]{2,}" e.txt
The number was 9.
9997
but we rounded it off to10
.0.
如果逗号也省略掉则表示重复固定的次数。 例如,[0-9]{3}
匹配3位数字
[root@shell-centos-1 ~]# egrep "[0-9]{3}" e.txt
The number was 9.
999
7 but we rounded it off to 10.0.
# (...)
特征标群
特征标群是一组写在 (...)
中的子模式。(...)
中包含的内容将会被看成一个整体,和数学中小括号( )的作用相同。例如, 表达式 (ab)*
匹配连续出现 0 或更多个 ab
。如果没有使用 (...)
,那么表达式 ab*
将匹配连续出现 0 或更多个 b
。再比如之前说的 {}
是用来表示前面一个字符出现指定次数。但如果在 {}
前加上特征标群 (...)
则表示整个标群内的字符重复 N 次。
我们还可以在 ()
中用或字符 |
表示或。例如,(c|g|p)ar
匹配 car
或 gar
或 par
.
[root@shell-centos-1 ~]# egrep "(c|g|p)ar" a.txt
The
car par
ked in thegar
age.
# |
或运算符
或运算符就表示或,用作判断条件。
例如 (T|t)he|car
匹配 (T|t)he
或 car
。
[root@shell-centos-1 ~]# egrep "(T|t)he|car" a.txt
The car
parked inthe
garage.
# 转码特殊字符
反斜线 \
在表达式中用于转码紧跟其后的字符。用于指定 { } [ ] / \ + * . $ ^ | ?
这些特殊字符。如果想要匹配这些特殊字符则要在其前面加上反斜线 \
。
例如 .
是用来匹配除换行符外的所有字符的。如果想要匹配句子中的 .
则要写成 \.
以下这个例子 \.?
是选择性匹配.
[root@shell-centos-1 ~]# egrep "(f|c|m)at\.?" d.txt
The
fat cat
sat on themat
.
# 锚点
在正则表达式中,想要匹配指定开头或结尾的字符串就要使用到锚点。^
指定开头,$
指定结尾。
# ^
号
^
用来检查匹配的字符串是否在所匹配字符串的开头。
例如,在 abc
中使用表达式 ^a
会得到结果 a
。但如果使用 ^b
将匹配不到任何结果。因为在字符串 abc
中并不是以 b
开头。
例如,^(T|t)he
匹配以 The
或 the
开头的字符串。
[root@shell-centos-1 ~]# egrep "^(T|t)he" a.txt
The car parked in the garage.
# $
号
同理于 ^
号,$
号用来匹配字符是否是最后一个。
例如,(at\.)$
匹配以 at.
结尾的字符串。
[root@shell-centos-1 ~]# egrep "(at\.)" d.txt
The fat cat sat on the m
at
.[root@shell-centos-1 ~]# egrep "(at\.)$" d.txt
The fat cat sat on the m
at
.
# 简写字符集
则表达式提供一些常用的字符集简写。如下:
简写 | 描述 |
---|---|
. | 除换行符外的所有字符 |
\w | 匹配所有字母数字,等同于 [a-zA-Z0-9_] |
\W | 匹配所有非字母数字,即符号,等同于: [^\w] |
\d | 匹配数字: [0-9] |
\D | 匹配非数字: [^\d] |
\s | 匹配所有空格字符,等同于: [\t\n\f\r\p{Z}] |
\S | 匹配所有非空格字符: [^\s] |
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\t | 匹配一个制表符 |
\v | 匹配一个垂直制表符 |
\p | 匹配 CR/LF(等同于 \r\n ),用来匹配 DOS 行终止符 |
# sed命令
# 简介
sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容
,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
# Sed的命令参数详解
[root@www ~]# sed [-nefr] [动作]
选项与参数:
-n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
-e :直接在命令列模式上进行 sed 的动作编辑;
-f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;
-r :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)
-i :直接修改读取的文件内容,而不是输出到终端。
动作说明: [n1[,n2]]function
n1, n2 :不见得会存在,一般代表『选择进行动作的行数』,举例来说,如果我的动作是需要在 10 到 20 行之间进行的,则『 10,20[动作行为] 』
function:
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g
# Sed的命令格式
命令 | 选项 | (s)sed命令功能(g)修饰符 | 参数(文件) |
---|---|---|---|
sed | -r | 's#oldboy#oldgirl#g' | oldboy.txt |
备注:前一步中执行的结果,并没有写回到a.txt中,如果想写回,则需要这样(添加-i参数)
# Sed核心应用
# Sed-查找
查找格式 | ||
---|---|---|
'1p' | 指定行号进行查找 | |
'1,5p' | 指定行号范围进行查找 | |
'/lidao/p' | 类似于grep过滤,//里面可以写正则 | |
'/10:00/,/11:00/p' | 表示范围的过滤 |
# 示例的文件使用如下
[root@shell-centos-3 ~]# cat oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
# 指定行号
[root@shell-centos-3 ~]# sed -n '3p' oldboy.txt
103,李导996,C00
# 默认输出
[root@shell-centos-3 ~]# sed '' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
# 指定行号范围
#查看1-3行的范围
[root@shell-centos-3 ~]# sed -n '1,3p' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
#查看3-6行的范围
[root@shell-centos-3 ~]# sed -n '3,6p' oldboy.txt
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
#查看4-最后一行的范围 这里使用$p
[root@shell-centos-3 ~]# sed -n '4,$p' oldboy.txt
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
# 过滤
过滤的方式又别分为正则表达式过滤和范围过滤两种
正则过滤的方式
[root@shell-centos-3 ~]# sed -n '/oldboy/p' oldboy.txt #就过滤oldboy
101,oldboy,CEO
[root@shell-centos-3 ~]# sed -n '/996/p' oldboy.txt #过滤996
103,李导996,C00
103,李导996,C00
[root@shell-centos-3 ~]# sed -n '/[45]/p' oldboy.txt #过滤使用正则4 5
104,yy,CFO
105,feixue,CIO
[root@shell-centos-3 ~]# sed -nr '/[0-9]{3}/p' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
范围过滤的方式
[root@shell-centos-3 ~]# sed -n '/102/,/105/p' oldboy.txt
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
表示范围过滤的时候,如果一直没有给到末尾的范围,就会一直显示到末尾。
# Sed-删除
删除格式 | ||
---|---|---|
'2p' | 指定行号进行查找 | |
'1,5d' | 指定行号范围进行查找 | |
'/lidao/d' | 类似于grep过滤,//里面可以写正则 | |
'/10:00/,/11:00/d' | 表示范围的过滤 | |
1,/oldboy/d | 混合(了解) |
# 最常规的删除
[root@shell-centos-3 ~]# sed '3d' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@shell-centos-3 ~]# sed '2d' oldboy.txt
101,oldboy,CEO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@shell-centos-3 ~]# sed '2,3d' oldboy.txt
101,oldboy,CEO
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@shell-centos-3 ~]# sed '/lidao/d' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
删除文件中的空行和包含#号的行数
[root@shell-centos-3 ~]# egrep -v '^$|#' /etc/ssh/sshd_config
[root@shell-centos-3 ~]# sed -r '/^$|#/d' /etc/ssh/sshd_config
[root@shell-centos-3 ~]# sed -nr '/^$|#/!p' /etc/ssh/sshd_config
# Sed-增加
增加格式 | 含义 |
---|---|
c | replace替代这行的内容 |
a | append追加,向指定的行或者每一行追加内容(行的后面) |
i | insert插入,向指定的行或者每一行插入内容 |
# 最常规的增加
[root@shell-centos-3 ~]# cat oldboy.txt #这是最初始的文件内容
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@shell-centos-3 ~]# sed '3a 996,lidao996.UFO' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
996,lidao996.UFO #在地三行的后面添加内容
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@shell-centos-3 ~]# sed '3i 996,lidao996.UFO' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
996,lidao996.UFO #在第三行的前面添加内容
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@shell-centos-3 ~]# sed '3c 996,lidao996.UFO' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
996,lidao996.UFO #替换第三行然后更改为需要替换的内容
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
向文件中追加多行内容
比如向sshd_config里面追加多行内容
UseDNS no
GSSAPIAUTCATION no
PermitRootLogin no
方法1:
cat >> config << EOF
方法2:
sed '$a UseDNS no\nGSSAPIAUTCATION no\nPermitRootLogin no' config
# Sed-替换
s--> sub substitute替换
g--> global 全局替换,sed替换每行所有匹配的内容,sed默认只是替换每行第一个匹配的内容
替换格式 |
---|
s###g |
s///g |
s@@@g |
# 最常规的替换
[root@shell-centos-3 ~]# sed 's#[0-9]##g' oldboy.txt
,oldboy,CEO
,zhangyao,CTO
,李导,C
,李导,C
,yy,CFO
,feixue,CIO
,lidao,COCO
[root@shell-centos-3 ~]# sed 's#[0-9]##' oldboy.txt
01,oldboy,CEO
02,zhangyao,CTO
03,李导996,C00
03,李导996,C00
04,yy,CFO
05,feixue,CIO
10,lidao,COCO
# Sed小总结:
删除:d命令
$ sed '2d' example -----删除example文件的第二行。
$ sed '2,$d' example -----删除example文件的第二行到末尾所有行。
$ sed '$d' example -----删除example文件的最后一行。
$ sed '/test/'d example -----删除example文件所有包含test的行。
替换:s命令
$ sed 's/test/mytest/g' example -----在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。
$ sed -n 's/^test/mytest/p' example -----(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。
$ sed 's/^192.168.0.1/&localhost/' example -----&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost。
$ sed -n 's/\(love\)able/\1rs/p' example -----love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。
$ sed 's#10#100#g' example -----不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。
选定行的范围:逗号
$ sed -n '/test/,/check/p' example -----所有在模板test和check所确定的范围内的行都被打印。
$ sed -n '5,/^test/p' example -----打印从第五行开始到第一个包含以test开始的行之间的所有行。
$ sed '/test/,/check/s/$/sed test/' example -----对于模板test和west之间的行,每行的末尾用字符串sed test替换。
多点编辑:e命令
$ sed -e '1,5d' -e 's/test/check/' example-----(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执 行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。
$ sed --expression='s/test/check/' --expression='/love/d' example-----一个比-e更好的命令是--expression。它能给sed表达式赋值。
从文件读入:r命令
$ sed '/test/r file' example-----file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面。
写入文件:w命令
$ sed -n '/test/w file' example-----在example中所有包含test的行都被写入file里。
追加命令:a命令
$ sed '/^test/a\--->this is a example' example<-----'this is a example'被追加到以test开头的行后面,sed要求命令a后面有一个反斜杠。
插入:i命令
$ sed '/test/i\new line-------------------------' example如果test被匹配,则把反斜杠后面的文本插入到匹配行的前面。
# 使用Sed修改配置文件示例
使用如下测试文件
[root@shell-centos-3 ~]# cat sh
centos
nginx
mysql
httpd
# 替换文件内容
- 替换文件内容,
替换centos为redhat
,然后再redhat的后面添加centos和在centos前面添加ubnutu
。
[root@shell-centos-3 ~]# sed -i 's/centos/redhat/g' sh
[root@shell-centos-3 ~]# cat sh
redhat
nginx
mysql
httpd
[root@shell-centos-3 ~]# sed -i '/redhat/a\centos' sh
[root@shell-centos-3 ~]# cat sh
redhat
centos
nginx
mysql
httpd
[root@shell-centos-3 ~]# sed -i '/centos/i\ubnutu' sh
[root@shell-centos-3 ~]# cat sh
redhat
ubnutu
centos
nginx
mysql
httpd
- 增加文件的内容,
在末尾添加三行abc
[root@shell-centos-3 ~]# sed -i '$a\abc\nabc\nabc' sh
[root@shell-centos-3 ~]# cat sh
redhat
ubnutu
centos
nginx
mysql
httpd
abc
abc
abc
- 将内容以
abc开头的修改成myjob
[root@shell-centos-3 ~]# sed -i 's/^abc/myjob/g' sh
[root@shell-centos-3 ~]# cat sh
redhat
ubnutu
centos
nginx
mysql
httpd
myjob
myjob
myjob
- 用grep
输出文件内容的行数
,然后在第7行的下面添加refine="0.1.0.12",dailysign="0.1.0.4",stonehenge="0.1.0.2"
,首行需要加两个空格。
[root@shell-centos-3 ~]# grep -n '.' sh
1:redhat
2:ubnutu
3:centos
4:nginx
5:mysql
6:httpd
7:myjob
8:myjob
9:myjob
[root@shell-centos-3 ~]# sed -i "7a \ refine=\"0.1.0.12\"\n dailysign=\"0.1.0.4\" \n stonehenge=\"0.1.0.2\"" sh
[root@shell-centos-3 ~]# cat sh
redhat
ubnutu
centos
nginx
mysql
httpd
myjob
refine="0.1.0.12"
dailysign="0.1.0.4"
stonehenge="0.1.0.2"
myjob
myjob
- 删除所有的
myjob
[root@shell-centos-3 ~]# sed -i '/myjob/d' sh
[root@shell-centos-3 ~]# cat sh
redhat
ubnutu
centos
nginx
mysql
httpd
refine="0.1.0.12"
dailysign="0.1.0.4"
stonehenge="0.1.0.2"
# AWK命令
# Awk是什么
Awk、sed与grep,俗称Linux下的三剑客,它们之间有很多相似点,但是同样也各有各的特色,相似的地方是它们都可以匹配文本,其中sed和awk还可以用于文本编辑,而grep则不具备这个功用。sed是一种非交互式且面向字符流的编辑器(a "non-interactive" stream-oriented editor),而awk则是一门模式匹配的编程语言
,因为它的主要功能是用于匹配文本并处理
,同时它有一些编程语言才有的语法,例如函数、分支循环语句、变量等等,当然比起我们常见的编程语言,Awk相对比较简单。
使用Awk,我们可以做以下事情:
将文本文件视为由字段和记录组成的文本数据库;
在操作文本数据库的过程中能够使用变量;
能够使用数学运算和字符串操作
能够使用常见的编程结构,例如条件分支与循环;
能够格式化输出;
能够自定义函数;
能够在awk脚本中执行UNIX命令;
能够处理UNIX命令的输出结果;
# 语法问题
Awk是一门编程语言,所以将awk的脚本视为一段代码。而awk的脚本同样可以写到一个文件中,并通过-f参数指定,这一点和sed是一样的。program一般多个pattern和action序列组成,当读入的记录匹配pattern时
,才会执行相应的action命令
。这里有一点要注意,在第一种形式中,除去命令行选项外,program参数一定要位于第一个位置
。
Awk的输入被解析成多个记录(Record)
,默认情况下,记录的分隔符是\n,因此可以认为一行就是一个记录,记录的分隔符可以通过内置变量RS
更改。当记录匹配某个pattern时,才会执行后续的action命令。
而每个记录由进一步地被分隔成多个字段(Field),默认情况下字段的分隔符是空白符,例如空格、制表符等等,也可以通过-F ERE
选项或者内置变量FS
更改。在awk中,可以通过$1,$2...来访问对应位置的字段,同时$0存放整个记录,这一点有点类似shell下的命令行位置参数。关于这些内容,我们会在下面详细介绍,这里你只要知道有这些东西就好。
标准的awk命令行参数主要由以下三个:
-F ERE
:定义字段分隔符,该选项的值可以是扩展的正则表达式(ERE);-f progfile
:指定awk脚本,可以同时指定多个脚本,它们会按照在命令行中出现的顺序连接在一起;-v assignment
:定义awk变量,形式同awk中的变量赋值,即name=value,赋值发生在awk处理文本之前;
# 特点和应用场景
- 类似于一门语言,C语言
- 过滤,统计,计算
- 过滤,统计日志
- BEGIN开始和END结尾
# 执行过程
[root@centos ~]# awk -F,'BEGIN{print "name"}{print $2}END{print "end of file"}' test.txt
[root@centos ~]# cat oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@centos ~]# awk -F, 'BEGIN{print "name"}{print $2}END{print "end of file"}' oldboy.txt
name
oldboy
zhangyao
李导996
李导996
yy
feixue
lidao
end of file
'这里使用BEGIN和END分别在开始和末尾打印,然后在取第三行的第二列的文本内容'
[root@centos ~]# cat oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@centos ~]# awk -F, 'BEGIN{print "name"}NR==3{print $2}END{print "end of file"}' oldboy.txt
name
李导996
end of file
举几个简单的例子。通过-F参数设置冒号:为分隔符,并打印各个字段:
[kodango@devops ~]$ echo "1:2:3" | awk -F: '{print $1 " and " $2 " and " $3}'
1 and 2 and 3
在awk的脚本中访问通过-v选项设置的变量:
[kodango@devops ~]$ echo | awk -v a=1 'BEGIN {print a}'
1
通过-v选项设置的变量在BEGIN
的位置就可以访问了。BEGIN
是一个特殊的pattern,它在awk处理输入之前就会执行,可以认为是一个初始化语句,与此对应的还有END
。
假设有两个文件:a和b,它们的内容分别如下所示:
[root@centos ~]# cat a
file a
[root@centos ~]# cat b
file b
为了说明赋值操作发生的时机,我们在BEGIN,正常处理,END三个地方都打印变量的值。
第一种情况: 变量赋值位于所有文件名参数之前:
[root@centos ~]# awk 'BEGIN {print "BEGIN: " var} {print "PROCESS: " var} \
END {print "END: " var }' var=1 a
BEGIN:
PROCESS: 1
END: 1
结果:赋值操作发生在正常处理之前,BEGIN
动作之后。
第二种情况:变量赋值位于所有文件名之后:
[kodango@devops awk_temp]$ awk 'BEGIN {print "BEGIN: " var} {print "PROCESS: " var} \
END {print "END: " var }' a var=1
BEGIN:
PROCESS:
END: 1
结果:赋值操作发生在正常处理之后,END
动作之前。
第三种情况:变量赋值位于文件名之间:
[kodango@devops awk_temp]$ awk 'BEGIN {print "BEGIN: " var} {print "PROCESS: " var} \
END {print "END: " var }' a var=1 b
BEGIN:
PROCESS:
PROCESS: 1
END: 1
# Awk的行与列
名词 | awk中的叫法 | 一些说明 |
---|---|---|
行 | 记录record | 每一行是默认回车分割的. |
列 | 字段,域field | 每一列默认是通过空格分割的. |
awk中行和列结束标语都是可以修改 |
# Awk中取行
常用的AWK条件 | |
---|---|
NR==1 | 取出某一行 |
NR>=1&&NR<=5 | 取出1到5行范围 |
符号 | > < >= <= != |
/oldboy/ | |
/101/,/105/ |
[root@centos ~]# awk 'NR==1' oldboy.txt
101,oldboy,CEO
[root@centos ~]# awk 'NR>=1 && NR<=5' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
[root@centos ~]# awk '/oldboy/' oldboy.txt
101,oldboy,CEO
[root@centos ~]# awk '/101/,/105/' oldboy.txt
101,oldboy,CEO
102,zhangyao,CTO
103,李导996,C00
103,李导996,C00
104,yy,CFO
105,feixue,CIO
# Awk中取列
-F
指定分隔符 指定每一列结果结束标记(默认是空格,连续的空格,tab健)$数字
: 表示取出某一列,在awk中$加上内容 就一个意思,表示取出某一列$0
整行的内容$NF
最后一列{print xxx}
默认取出第五列和第九列
[root@centos yum.repos.d]# ls -l | awk '{print$5,$9}' | column -t
1664 CentOS-Base.repo
1309 CentOS-CR.repo
649 CentOS-Debuginfo.repo
314 CentOS-fasttrack.repo
630 CentOS-Media.repo
1331 CentOS-Sources.repo
4768 CentOS-Vault.repo
'取出第一列和最后一列'
[root@centos yum.repos.d]# ls -l | awk '{print $1,$NF}' | column -t
total 32
-rw-r--r--. CentOS-Base.repo
-rw-r--r--. CentOS-CR.repo
-rw-r--r--. CentOS-Debuginfo.repo
-rw-r--r--. CentOS-fasttrack.repo
-rw-r--r--. CentOS-Media.repo
-rw-r--r--. CentOS-Sources.repo
-rw-r--r--. CentOS-Vault.repo
'在中间添加点东西'
[root@centos yum.repos.d]# ls -l | awk '{print $1,"aaaaaa "$NF}' | column -t
total aaaaaa 32
-rw-r--r--. aaaaaa CentOS-Base.repo
-rw-r--r--. aaaaaa CentOS-CR.repo
-rw-r--r--. aaaaaa CentOS-Debuginfo.repo
-rw-r--r--. aaaaaa CentOS-fasttrack.repo
-rw-r--r--. aaaaaa CentOS-Media.repo
-rw-r--r--. aaaaaa CentOS-Sources.repo
-rw-r--r--. aaaaaa CentOS-Vault.repo
使用awk互相调换第一列和最后一列的位置
[root@centos etc]# awk -F: '{print $NF,$2,$3,$4,$5,$6,$1}' passwd
/bin/bash x 0 0 root /root root
/sbin/nologin x 1 1 bin /bin bin
/sbin/nologin x 2 2 daemon /sbin daemon
/sbin/nologin x 3 4 adm /var/adm adm
/sbin/nologin x 4 7 lp /var/spool/lpd lp
/bin/sync x 5 0 sync /sbin sync
/sbin/shutdown x 6 0 shutdown /sbin shutdown '这样的内容是没有冒号的,文件内容中的:号变成了空格,所以需要替换为:'
[root@centos etc]# awk -F: -vOFS=: '{print $NF,$2,$3,$4,$5,$6,$1}' passwd
/bin/bash:x:0:0:root:/root:root
/sbin/nologin:x:1:1:bin:/bin:bin
/sbin/nologin:x:2:2:daemon:/sbin:daemon
/sbin/nologin:x:3:4:adm:/var/adm:adm
/sbin/nologin:x:4:7:lp:/var/spool/lpd:lp
/bin/sync:x:5:0:sync:/sbin:sync
/sbin/shutdown:x:6:0:shutdown:/sbin:shutdown
# 小结
- 行与列 名称
- awk取行与取列,指哪打哪
取出网卡的ip地址
[root@centos etc]# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:c4:a5:85 brd ff:ff:ff:ff:ff:ff
inet 172.25.253.7/24 brd 172.25.253.255 scope global dynamic eth0
valid_lft 52721sec preferred_lft 52721sec
inet6 fe80::f816:3eff:fec4:a585/64 scope link
valid_lft forever preferred_lft forever
[root@centos etc]# ip a | grep inet | awk 'NR==3' | awk -F"[ /]+" '{print $3}'^C
[root@centos etc]# ip a | grep inet | awk -F"[ /]+" 'NR==3{print $3}'
172.25.253.7
# Awk模式匹配
awk -F"[/]+" 'NR==3{print $3}'
awk | -F"[/]+" | 'NR==3{print $3}' |
---|---|---|
命令 | 选项 | '条件{动作}' |
'找谁{干啥}' | ||
'模式{动作}' | ||
'pattern{action}' |
- 比较符号: > < >= <= != ==
- 正则: 支持grep的正则
- 表示范围的://,//
- 特殊条件:BEGIN和END
# Awk正则匹配
- //支持扩展正常
- awk可以精确到某一列中包含/不包含..内容 ~
- ~包含
- !~不包含
正则 | awk正则 |
---|---|
^ 表示以...开头的行 | 某一列的开头 $3~/^oldboy/ |
$ 表示以...结尾的行 | 某一列的结尾 $4~/lidao$/ |
^$ 表示空行1 | 某一列是空的 |
'找出第三列的以1开头的'
[root@centos etc]# awk -F: '$3~/^1/' passwd
bin:x:1:1:bin:/bin:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
centos:x:1000:1000:Cloud User:/home/centos:/bin/bash
'找出第三列以2开头的 然后打印第一列第三列和最后一列'
[root@centos etc]# awk -F: '$3~/^2/{print $1 $3,$NF}' passwd
daemon2 /sbin/nologin
rpcuser29 /sbin/nologin
'找出第三列以1或者2开头的 然后打印第一列第三列和最后一列'
[root@centos etc]# awk -F: '$3~/^[12]/{print $1 $3,$NF}' passwd
bin1 /sbin/nologin
daemon2 /sbin/nologin
operator11 /sbin/nologin
games12 /sbin/nologin
ftp14 /sbin/nologin
systemd-network192 /sbin/nologin
rpcuser29 /sbin/nologin
centos1000 /bin/bash
[root@centos etc]# awk -F: '$3~/^1|2/{print $1 $3,$NF}' passwd
[root@centos etc]# awk -F: '$3~/^1|^2/{print $1 $3,$NF}' passwd
[root@centos etc]# awk -F: '$3~/^(1|2)/{print $1 $3,$NF}' passwd
# Awk表示范围
- /哪里开始/,/哪里结束/ 常用
- NR==1,NR==5 从第一行开始到第5行结束 类似于sed -n '1,5p'
'统计范围然后打印第1列和第3列'
[root@centos ~]# awk -F"[ ,]+" '/102/,/105/{print $1,$3}' oldboy.txt
102 CTO
103 C00
103 C00
104 CFO
105 CIO
# Awk特殊模式BEGIN{}和END{}
模式 | 含义 | 应用场景 |
---|---|---|
BEGIN{} | 里面的内容会在awk读取文件之前执行 | 1)进行简单统计,计算,不涉及读取文件(常见) 2)用来处理文件之前,添加个表头 3)用来定义awk变量(很少用,因为可以用-v) |
END{} | 里面的内容会在awk读取文件之后执行 | 1)awk进行统计,一般过程:先进行计算,最后END里面输出结果 2)awk使用数组,用来输出数组的结果(常见) |
END{}统计计算
:
统计方法:
统计方法 | 简写形式 | 应用场景 |
---|---|---|
i++ | i=i+1 | 计数,统计次数 |
sum=sum+??? | sum+=??? | 求和累加 |
array[]=array[]+1 | array[]++ | 数组分类计数 |
注意:i,sum都是变量 |
'统计/etc/services里面有多少个空行'
[root@centos etc]# awk '/^$/' services
·
·
·
#使用条件加动作打印结果
[root@centos etc]# awk '/^$/{i++}END{print i}' services
17
'使用seq 100求和1+2+3..+100 awk实现'
[root@centos etc]# seq 100 | awk '{sum=sum+$1}END{print sum}'
5050
如果想查看过程
[root@centos etc]# seq 100 | awk '{sum=sum+$1;print sum}END{print sum}'
# Awk数组
统计日志
:类似于 统计每个ip出现的次数,统计每种状态码出现的次数,统计系统中每个用户被攻击的次数,统计攻击者的ip出现次数。累加求和
:统计每个ip消耗的流量。
shell数组 | awk数组 | ||
---|---|---|---|
形式 | array[0]=oldboy array[1]=lidao | array[0]=oldboy array[1]=lidao | |
使用 | echo ${array[0]} ${array[1]} | print array[0] array[1] | |
批量输出数组内容 | for i in ${array[*]} do echo $i done | for(i in array) print array[i] | awk数组专用循环,变量获取到的是数组的下标. 如果想要数组内容a[i] |
'awk字母会被识别为变量,如果只是想要使用字符串需要使用双引号引起来'
[root@centos etc]# awk 'BEGIN{a[0]=oldboy;a[1]=lidao; print a[0],a[1]}' #这里会打印空行
[root@centos etc]# awk 'BEGIN{a[0]="oldboy";a[1]="lidao"; print a[0],a[1]}'
oldboy lidao
[root@centos etc]# awk 'BEGIN{a[0]=12360;a[1]=12360; print a[0],a[1]}'
12360 12360
'awk数组专用循环,变量获取到的是数组的下标'
[root@centos etc]# awk 'BEGIN{a[0]=12360;a[1]=12360; for(i in a )print i}'
0
1
'加上array[]'
[root@centos etc]# awk 'BEGIN{a[0]=12360;a[1]=12360; for(i in a )print a[i]}'
12360
12360
处理以下文件内容,将域名取出来并根据域名进行计数排序处理
[root@centos etc]# cat url.txt
http://www.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html
[root@centos etc]# awk -F"[/.]+" '{print $2}' url.txt
www
www
post
mp3
www
post
'array[]++ 你要统计三年 []里面就是什么(某一列)'
[root@centos etc]# awk -F"[/.]+" '{array[$2]++}END{for(i in array)print i,array[i]}' url.txt
www 3
mp3 1
post 2
# for循环
for i in 123
do
echo $i
done
shell编程c语言for循环 | awk for循环 | |
---|---|---|
for((i=1;1<=10;i++)) do echo $i done | for(i=1;i<=10;i++) print i | awk循环用来循环每个字段 |
'1+100'
[root@centos etc]# awk 'BEGIN{for(i=1;i<=100;i++)sum+=i;print sum}'
5050
[root@centos etc]# awk 'BEGIN{
for(i=1;i<=100;i++)
sum+=i;
print sum
}'
5050
'显示详细过程'
[root@centos etc]# awk 'BEGIN{
for(i=1;i<=100;i++)
{sum+=i;
print sum}
}'
5050
# if判断
shell if判断 | awk if | |
---|---|---|
if["oldboy" -eq 18];then echo take to dbj fi | if(条件) print"dbj" | 常用 |
if["oldboy" -eq 18];then echo take to "dbj" else echo "rest" fi | if(条件) print"dbj" else print"rest" | |
统计磁盘空间使用率,如果大于70%,则提示磁盘空间不足,并且显示磁盘分区,磁盘使用率,磁盘挂载点
[root@centos etc]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 20G 967M 20G 5% /
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 17M 1.9G 1% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
tmpfs 379M 0 379M 0% /run/user/0
[root@centos etc]# df -h | awk -F"[ %]+" '{if($5>=70)print "disk not enough"}'
disk not enough
[root@centos etc]# df -h | awk -F"[ %]+" '{if($5>=70)print "disk not enough",$0}' #这里会发现只打印了头上那行
disk not enough Filesystem Size Used Avail Use% Mounted on
[root@centos etc]# df -h | awk -F"[ %]+" 'NR>1{if($5>=70)print "disk not enough",$1,$5}' #这里会发现没有>=70%
[root@centos etc]# df -h | awk -F"[ %]+" 'NR>1{if($5>=1)print "disk not enough",$1,$5}' #直接缩小到1%
disk not enough /dev/vda1 5
disk not enough tmpfs 1
'需要注意的是: awk使用多个条件的时候 第1个条件可以放在 "条件{动作} 第2个条件 一般使用if"'
统计这段语句中,单词中字符小于6的单词,显示出来。
[root@centos ~]# echo I am oldboy teacher welcome to oldboy traning class. | awk -F"[ .]+" '{for(i=1;i<=NF;i++)print $i}'
I
am
oldboy
teacher
welcome
to
oldboy
traning
[root@centos ~]# echo I am oldboy teacher welcome to oldboy traning class. | awk -F"[ .]+" '{
for(i=1;i<=NF;i++)
if(length($i)<6)
print $i
}'
I
am
to
class
[root@centos ~]# echo oldboy | awk '{print length($1)}'
6
[root@centos ~]# echo oldboy tom | awk '{print length(1)}'
1
[root@centos ~]# echo oldboy tom | awk '{print length($1)}'
6
[root@centos ~]# echo oldboy tom | awk '{print length($2)}'
3
# Awk的内置变量
内置变量 | ||
---|---|---|
NR | Number of Record 记录号,行 | |
NF | Number of Field 每行有多个字段(列)$NF表示最后一列 | |
FS | -F: === -v FS=: Field Separator 字段分隔符,每个字段结束标记 | |
OFS | Output Field Separator 输出字段分隔符(awk显示每一列之间通过什么分割,默认空格) |
# 总结
- gawk gnu awk
- awk选项 -F -v
- awk的执行流程
- awk的取行取列: 指哪打哪
- awk模式: 正则,范围,特殊模式,比较
- awk数组: 统计分析日志
- awk for if
- man awk /info awk