三剑客

awk

awk是一种编程语言,主要用于在linux/unix下对文本和数据进行处理,是linux/unix下的一个工具。数据可以来自标准输入、一个或多个文件,或其它命令的输出。
awk的处理文本和数据的方式:逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作

awk的语法:
awk [options] 'commands(地址定位)' file(s)
options 部分
 -F 定义字段分割符号,默认的分隔符是空格
-v 定义变量并赋值
command 部分:
'范围说明或正则表达式或者{awk命令语句1;awk命令语句2;...}'
'BEGIN{}       {}         END{}'
行处理前     行处理 行处理后

1、范围说明部分可以是BEGIN、END、逻辑表达式或者为空
2、awk命令语句间用分号间隔
3、引用shell变量需用双引号引起

awk的工作原理:
# awk -F: '{print $1,$3}' /etc/passwd
(1)awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符(RS)结束

(2)然后,行被:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始。

(3)awk如何知道用空格来分隔字段的呢? 因为有一个内部变量FS来确定字段分隔符。初始时,FS赋为空格

(4)awk打印字段时,将以设置的方法使用print函数打印,awk在打印的字段间加上空格,因为$1,$3之间
有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格

(5)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔
成字段并进行处理。该过程将持续到所有行处理完毕

awk的基本应用:
$0 :表示当前所有记录
$1,$2,$3...$n:awk中用该顺序形式表示files中每行以间隔符号分割的各列的不同字段
注:
awk默认以空格符为间隔符号将每行分割为单独的字段,也可以使用awk内置变量FS定义间隔符号
awk -F: ''
awk 'BEGIN{FS=":"}'

NF 表示当前记录的字段数(列数)
$NF 最后一列
$(NF-1) 倒数第二列
FNR/NR 行号
FILENAME 文件名
"\t" 制表符
"\n" 换行符
"" 打印字符串
FS 定义间隔符
OFS 定义输出字段分隔符
RS 输入记录分割符,默认换行
ORS 输出记录分割符,默认换行
print 打印函数


一:
创建一个文件1.txt

my first language:Java
second languange:python
third language:C


用法:
1、awk '{print $0}' 1.txt 表示print表示打印, $0 表示整个记录,1.txt表示一个文件,所以此条指令的结果就是把这整个文件打印出来
结果:
my first language:Java
second languange:python
third language:C


2、awk '{print $1}' 1.txt 表示:打印文本的第一列
结果:
my
second
third


3、awk -F ':' '{print $2}' 1.txt   表示以":"为分隔符,打印第2列  -F表示指定分割符,也可以是要查询的文本中的其他分割符。
结果:
Java
python
c


4、awk -F ':' '$2=="Java"{print $2}' 表示以":"为分隔符,限制在":"分隔符的第二列为Java的那一项
结果:
Java


5、awk -F ':' 'NR % 2 ==1 {print $2}' 1.txt 表示:打印奇数行的第二个字段 NR是一个内置的变量,表示当前正在处理的记录,即当前的记录是第几个记录。
结果:
Java
c


6、awk '{if(NR >1) print $2}' 1.txt 表示打印第二个及其以后的记录,上面的字段分隔符是空格了,并且 if 语句是在“{}” 里指定的。
结果:
languange:python
language:C


7、awk '{if($1 < "s") print $1; else print $2}' 1.txt 表示:如果第一个字段大于“s",则打印第一个字段,否则打印第二个字段。
结果:
my
languange:python
language:C


8、awk提供了一些内置函数来供我们使用,以下常用的函数如下:
tolower():字符转为小写。
toupper():字符转为大写
length():返回字符串长度。
substr():返回子字符串。
sqrt():平方根。
rand():随机数。
例子:
awk '{print toupper($1)}' 1.txt
结果:
MY
SECOND
THIRD



9、变量
ARGC:命令行参数个数
ARGV:命令行参数排列
ENVIRON:支持队列中系统环境变量的使用
NR:表示当前处理的是第几行,即已读的记录数
NF:表示当前行有多少个字段,即浏览记录的域的个数
FILENAME:awk浏览的当前文件名
FS:字段分隔符,默认是空格和制表符。设置输入域分隔符,等价于明令行-F选项
RS:行分隔符,用于分割每一行,默认是换行符。控制记录分隔符
OFS:输出字段的分隔符,用于打印时分隔字段,默认为空格。 输出记录分割符
ORS:输出记录的分隔符,用于打印时分隔记录,默认为换行符。 输出域分割符

小知识点:
awk工作流程是这样的:读入有’n’换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是”空白键” 或 “键”,所以$1表示登录用户,$3表示登录用户ip,以此类推。

$0 代表整个文本行
$1 代表文本行的第一个数据段
$n 代表文本行的第n个数据段

在文本行中,每个数据段都是通过字段分隔符划分的。gawk在读取一行文本时,会用预定义的字段分隔符划分每个字段。gawk中默认的字段分隔符是任意的空白字符(例如空格或者制表符)。
例如,用-F指定字段分隔符。显示系统密码文件的第一个数据字段。由于/etc/passwd用冒号来分隔数据字段,因而可以将冒号指定为字段分隔符。


其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。

gawk option program file
  选项:     描述
   -F fs           指定行中划分数据字段的字段分隔符
   -f file         从指定的文件中读取程序
   -v var=value       定义gawk程序中的一个变量及其默认值
   -mf N           指定要处理的数据文件中的最大字段数
   -mr N           指定数据文件中的最大数据行数
   -W keyword     指定gawk的兼容模式或警告等级


例子:
awk '{print $NF}' 1.txt 表示:打印每一个记录的最后一个字段
结果:
language:Java
languange:python
language:C
例子:
awk '{print NR "." $0}' 1.txt
结果:
1.my first language:Java
2.second languange:python
3.third language:C



二:
创建一个文件,内容为:
root     pts/1   192.168.1.100 Tue Feb 10 11:21   still logged in
root     pts/1   192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41)
root     pts/1   192.168.1.100 Mon Feb  9 11:41 - 18:30 (06:48)
dmtsai   pts/1   192.168.1.100 Mon Feb  9 11:41 - 11:41 (00:00)
root     tty1                   Fri Sep  5 14:09 - 14:10 (00:01)


用法:
1、只显示最近登录的5个账号
last -n 5 | awk '{print $1}' 或者  awk '{print $1}'
结果:
root
root
root
dmtsai
root

 

 

 

grep

grep命令的基本语法是:
grep [-acinv] [--color=auto] '搜寻字符串' filename
选项与参数:
grep用于根据关键字进行行过滤
OPTIONS:
   -i: 不区分大小写
   -v: 查找不包含指定内容的行,反向选择
   -w: 按单词搜索
   -o: 打印匹配关键字
   -c: 统计匹配到的次数
   -n: 显示行号
   -r: 逐层遍历目录查找
   -A: 显示匹配行及前面多少行
   -B: 显示匹配行及后面多少行
   -C: 显示匹配行前后多少行
   -l:只列出匹配的文件名
   -L:列出不匹配的文件名
   -e: 使用正则匹配
   -E:使用扩展正则匹配
  ^key:以关键字开头
  key$:以关键字结尾
  ^$:匹配空行
   --color=auto :可以将找到的关键词部分加上颜色的显示
   
实例介绍:
创建以下两个文件
$ cat re-file
I had a lovely time on our little picnic.
Lovers were all around us. It is springtime. Oh
love, how much I adore you. Do you know
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them? I can only hope love
is forever. I live for you. It's hard to get back in the
groove.、

$ cat linux.txt
Linux is a good
god assdxw bcvnbvbjk
greatttttt wexcvxc
operaaaating dhfghfvx
gooodfs awrerdxxhkl
gdsystem awxxxx
glad
good
 
用法实战:
1、匹配以love开头的所有行
grep '^love' re-file
结果:
love, how much I adore you. Do you know

2、匹配love结尾的所有行
grep 'love$' re-file
结果:
clover. Did you see them? I can only hope love

3、匹配以l开头,中间包含两个字符,结尾是e的所有行
grep 'l..e' re-file
结果:
I had a lovely time on our little picnic.
love, how much I adore you. Do you know
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them? I can only hope love.
is forever. I live for you. It's hard to get back in the

4、匹配0个或多个空行,后面是love的字符
grep ' *love' re-file
结果:
I had a lovely time on our little picnic.
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them? I can only hope love

5、匹配love或者Love
grep '[Ll]ove' re-file 对l不区分大小写
结果:
I had a lovely time on our little picnic.
Lovers were all around us. It is springtime. Oh
love, how much I adore you. Do you know
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them? I can only hope love

6、匹配A-Z的子母,其次是ove
grep '[A-Z]ove' re-file
结果:
I had a lovely time on our little picnic.
Lovers were all around us. It is springtime. Oh
love, how much I adore you. Do you know
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them? I can only hope love
[root@T-7 ceshi]# grep '[A-Z]ove' re-file
Lovers were all around us. It is springtime. Oh

7、匹配不在A-Z范围之内的任何字符行,所有的小写字符
grep '[^A-Z]' re-file
结果:
I had a lovely time on our little picnic.
Lovers were all around us. It is springtime. Oh
love, how much I adore you. Do you know
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them? I can only hope love
is forever. I live for you. It's hard to get back in the
groove.

8、匹配love
grep 'love\.' re-file
结果:
clover. Did you see them? I can only hope love.

9、匹配空格
grep '^$' re-file
结果:为空什么都没有

10、匹配任意字符
grep '.*' re-file
结果:
I had a lovely time on our little picnic.
Lovers were all around us. It is springtime. Oh
love, how much I adore you. Do you know
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them? I can only hope love.
is forever. I live for you. It's hard to get back in the
groove.

11、匹配前面o字符重复2到4次
grep 'o\{2,4\}' re-file
结果:
groove.

12、匹配重复o字符至少2次
grep 'o\{2,\}' re-file
结果:
groove.

13、匹配重复o字符最多2次
grep 'o\{,2\}' re-file
结果:
I had a lovely time on our little picnic.
Lovers were all around us. It is springtime. Oh
love, how much I adore you. Do you know
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them? I can only hope love.
is forever. I live for you. It's hard to get back in the
groove.

14、重复前一个字符一个或一个以上
egrep 'go+d' linux.txt
结果:
god assdxw bcvnbvbjk
gooodfs awrerdxxhkl
good

15、重复前一个字符0个或者一个字符
egrep  'go?d' linux.txt
结果:
god assdxw bcvnbvbjk
gdsystem awxxxx

16、查找多个字符串
egrep 'gd|good' linux.txt
结果:
Linux is a good
god assdxw bcvnbvbjk
gooodfs awrerdxxhkl
good

17、分组过滤匹配
egrep 'g(la|oo)d' linux.txt
结果:
Linux is a good
glad
good



#位置锚定:定位出现的位置
^ 行首锚定,用于面试的最左侧
$ 行尾锚定,用于模式的最右侧
^PATTERN$ 用于模式匹配整行
^$ 空行
^[[:space:]]*$ 空白行
\<或\b词首锚定,用于单词模式的左侧
\>或\b词尾锚定,用于单词模式的右侧
\<PATTERN\>匹配整个单词


 

sed

sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行输入,要么存储在一个命令文件中。sed会执行下列操作:

(1)一次从输入中读取一行数据。

(2)根据所提供的编辑器命令匹配数据

(3)安装命令修改流中的数据

(4)将新的数据输出到STDOUT

在流编辑器将所有命令与一行数据匹配完毕后,它会读取下一行数据并重复这个过程。在流编辑器处理完流中的所有数据行后,它就会终止。

由于命令是按顺序逐行执行的,sed编辑器只需对数据流进行以便处理就可以完成编辑操作。这使得sed编辑器要比交互式编辑器快得多,可以快速完成对数据的自动修改。

用法
sed [option]… '地址定位' intputfile
option:
-n:不输出模式空间内容到屏幕,既不自动打印
-e:多点编辑,即对输入行应用多条sed命令时使用
-f:/PATH/SCRIPT_FILE:从指定文件中读取编辑脚本
-r:支持使用扩展正则表达式
-i.bak:备份文件并原处编辑
-i inplace,原地编辑(修改源文件)

常用命令和选项:
命令1:
p 打印行
d 删除行
i\ 在当前行之前插入文本。多行时除最后一行外,每行末尾需用"\"续行
a\ 在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用“\”续行
c\ 用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用"\"续行
命令2:
r 从文件中读取输入行
w 将所选的行写入文件
! 对所选行以外的所有行应用命令,放到行数之后
s 用一个字符串替换另一个
g 在行内进行全局替换
&   保存查找串以便在替换串中引用   \(xxxxx\)
=   打印行号

script:
"地址命令"

2 地址定界

(1)不给地址:对全文进行处理

(2)单地址:
#:指定的行

/pattern/:被此处模式所能够匹配到的每一行

(3)地址范围:
#,#
#,+#
/pat1/,/pat2/
#,/pat1/

(4)~:步进
1~2 奇数行
2~2 偶数行

3 基本编辑命令
d:删除模式空间匹配的行
p:显示模式空间中的内容
a[\]text:在指定行后面追加文本,支持使用\n实现多行追加
i[\]text:在行前面插入文本
c[\]text:替换行为单行或多行文本
w /path/somefile:保存模式匹配的行至指定文件
r /path/somefile:读取指定文件的文本至模式空间中匹配到的行后
= :为模式空间中的行打印行号
! :模式空间中匹配行取反处理
s/oldstr/newstr/:查找替换,支持使用其它分隔符,s@@@,s###
替换标记:
  g:行内全局替换
  p:显示替换成功的行
  w /PATH/TO/SOMEFILE:将替换成功的行保存至文件中
   
   
用法:(这里的/etc/passwd每个虚拟机上都有这个文件,此处是借用的,要复制一份,以免弄坏了原文件)

1、sed -n '2p' passwd 表示打印第N行
结果:
bin:x:1:1:bin:/bin:/sbin/nologin

2、sed -n '1,4p' passwd 表示打印N到M行
结果:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

3、sed -n '/root/p' passwd 表示打印所有包含关键字string的行,也就是root
结果:
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

4、sed -n '1,/root/p' passwd 表示打印从第N行开始到有关键字string的所有行
结果:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

5、sed -n '/^$/=' /etc/passwd 表示显示空行行号 (此处的空行是自己人为故意弄出来的,实际上没有,为了测试)
结果:
46

6、sed '/root/a\superman' passwd 表示在关键字后追加文字,也就是在匹配到root的那一行的后面添加一行superman
结果:
root:x:0:0:root:/root:/bin/bash
superman
.....
operator:x:11:0:operator:/root:/sbin/nologin
superman

7、sed '/root/i\superman' passwd 表示:在关键字行前追加superman这个
结果:
superman
root:x:0:0:root:/root:/bin/bash
....
superman
operator:x:11:0:operator:/root:/sbin/nologin

8、sed '/root/c\superman' passwd 表示替换行为单行或多行文本 也就是把匹配到有root的行替换为superman
结果:
superman
bin:x:1:1:bin:/bin:/sbin/nologin
...
superman
games:x:12:100:games:/usr/games:/sbin/nologin

9、sed '1,10d' passwd 表示删除指定行 即删除了从1到10行
结果:
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

10、sed '2a tea' passwd 表示在第二行后再添加一行 tea,
结果:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
tea

11、sed -n 's/root/&superman/p' passwd 表示在关键字追加文本 即在匹配到的所有的root的后面直接跟着Superman
结果:
rootsuperman:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/rootsuperman:/sbin/nologin

12、sed -n 's/root/superman&/p' passwd 表示在关键字追加文本 即在匹配到的所有的root的前面直接跟着Superman
结果:
supermanroot:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/supermanroot:/sbin/nologin

13、sed -n 's/root/&superman&/p' passwd 表示在关键字追加文本 即在匹配到的所有的root的后面跟着superman再跟着root
结果:
rootsupermanroot:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/rootsupermanroot:/sbin/nologin


复制一份/etc/fstab 文件到自己测试的地方为fstab

14、sed 's/UUID/hahaha/g' fstab 表示在fstab文件中,查找到所有UUID的替换为hahaha
结果:
#
/dev/mapper/centos-root /                       xfs     defaults       0 0
hahaha=0ae3d94d-dfce-4bd7-947b-a290939a7af6 /boot                   xfs     defaults       0 0
/dev/mapper/centos-home /home  

15、sed -e 's/UUID/hahaha/g' -e 's/=/###/g' fstab 表示在fstab文件中,匹配查找到所有UUID的 替换为hahaha 并把匹配到的=替换为### 两条指令同时执行
结果:
/dev/mapper/centos-root /                       xfs     defaults       0 0
hahaha###0ae3d94d-dfce-4bd7-947b-a290939a7af6 /boot  

16、sed -i.bak 's/=/$$$$/g' fastab 表示修改前备份
结果:

[root@T-7 ceshi]# sed -i.bak 's/=/$$$$/g' fstab
[root@T-7 ceshi]# ll
总用量 28
-rw-r--r-- 1 root root   64 1月 10 19:27 1.txt
-rw-r--r-- 1 root root 331 1月 10 20:03 2.txt
-rw-r--r-- 1 root root 544 1月 10 22:12 fstab
-rw-r--r-- 1 root root 541 1月 10 22:05 fstab.bak

创建一个script1.sed文件
内容:
s/=/$$$$/
s/UUID/mytest/
意思为:搜索到的=替换为$$$$,搜索到的UUID替换为mytest

17、sed -f script1.sed fstab 表示 从script1.sed文件中读取sed的操作指令,用在fstab文件上
结果:
/dev/mapper/centos-root /                       xfs     defaults       0 0
mytest$$$$0ae3d94d-dfce-4bd7-947b-a290939a7af6 /boot                   xfs     defaults       0 0

 

 

正则

第一类正则:
(1). 任意单个字符,除了换行符
(2)* 前导字符出现0次或连续多次  ab*能匹配“a”,“ab”以及“abb”,但是不匹配“cb”
grep abcd*  1.txt abc abcd abcdd abcddddd

(3).* 任意长度的字符
(4)^ 行的开头
(5)$ 行的结尾
(6)^$ 空行


(7)[] 匹配指定字符组内的任一单个字符  
(8)[^] 匹配不在指定字符组内的任一字符

(9)^[] 匹配以指定字符组内的任一字符开头  
(10)^[^] 匹配不以指定字符组内的任一字符开头  



(11)\< 取单词的头
(12)\> 取单词的尾
(13)\<\> 精确匹配符号

(14)\{n\} 匹配前导字符连续出现n次
(15)\{n,\} 匹配前导字符至少出现n次
(16)\{n,m\} 匹配前导字符出现n次与m次之间

(17) \(\) 保存被匹配的字符

实例:
将192.168.0.254 换成 192.168.1.254
vim 1.txt
:%s#\(192\.168\)\.0\.\(254\)#\1\.100\.\2 //底行模式下匹配
将10.1.1.1替换成10.1.1.254
:%s#\(10.1.1\).1#\1.254#g
:%s/\(10.1.1\).1/\1.254/g

# sed -n 's#\(192\.168\)\.0\.254#\1\.1\.254#p'      
找出含有192.168的行,同时保留192.168并标记为标签1,之后可以使用\1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个。

[root@server shell05]# sed -n 's#10.1.1.1#10.1.1.254#p' 1.txt
10.1.1.254
[root@server shell05]# sed -n 's#\(10.1.1\).1#\1.254#p' 1.txt
10.1.1.254

将helloworld yourself 换成hellolilei myself

vim 1.txt
:%s#\(hello\)world your\(self\)#\1lilei my\2#g

# sed -n 's/\(hello\)world your\(self\)/\1lilei my\2/p' 1.txt
hellolilei myself

[root@server shell05]# sed -n 's/helloworld yourself/hellolilei myself/p' 1.txt
hellolilei myself
[root@server shell05]# sed -n 's/\(hello\)world your\(self\)/\1lilei my\2/p' 1.txt
hellolilei myself


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


扩展正则:
扩展正则的正则表达式grep -E 或者 egrep
扩展正则表达式元字符
+ 匹配一个或多个前导字符 bo+ boo bo
? 匹配零个或一个前导字符 bo? b bo
a|b   匹配a或b
() 组字符   hello myself yourself     (my|your)self

x{n} 前导字符x重复m次 \{n\}
x{n,} 前导字符x重复至少m次 \{n,\}
x{n,m} 前导字符x重复m到n次 \{n,m\}

实例:
# grep "root|ftp|adm" /etc/passwd
# egrep "root|ftp|adm" /etc/passwd
# grep -E "root|ftp|adm" /etc/passwd

# grep -E 'o+gle' test.txt
# grep -E 'o?gle' test.txt

# egrep 'go{2,}' 1.txt
# egrep '(my|your)self' 1.txt

 

posted on 2020-01-03 15:12  九酒馆  阅读(271)  评论(0编辑  收藏  举报

导航