Shell脚本的学习心得和知识总结(五)|文件处理命令三剑客(sed、awk)

2020年3月21日09:20:19
之前已经学习过 文本处理三剑客中的grep(egrep),今天来看其他两个命令:awk、sed。

文本处理命令

命令 描述
grep 默认不支持扩展表达式,加-E 选项开启 ERE。如果不加-E 使用花括号要加转义符 \ { \ }
egrep 都支持
awk 支持 同egrep
sed 默认不支持扩展表达式,加-r 选项开启 ERE。如果不加-r 使用花括号要加转义符\ { \ }

下面是sed命令:

[root@localhost shell_study]# 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, --unbuffered
                 load minimal amounts of data from the input files and flush
                 the output buffers 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: <[email protected]>.
Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.

sed命令

sed详解
  • 在Linux中 “一切皆文件”,但在使用常见的vim、cat、more等命令时,对诸如日志文件 配置文件等较大文件的编辑查询的效率并不是很高。而sed 命令是利用脚本来处理文本文件,即:可依照脚本的指令来处理、编辑文本文件。它主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。 因此,使用awk sed grep等这些工具,就可以在达到同样效果的前提下节省大量的重复性工作成本,提高工作效率。(繁杂的重复性文件操作:删除 增加 注释 修改等 + 大量需要操作的文件 = 人力物力财力被浪费)
  • 与vim等不同的是:被处理的文件内容可以是来自文件,也可以直接来自键盘或管道等标准输入。最后的结果默认情况下是显示到终端的屏幕上,但是也可以输出到文件中,且无需全部将其加载至内存中。
sed 命令
---------------------------------------------------------------------
语法格式如下:
sed [选项]  [sed命令]  [输入文件(需要修改的文件)]
或:sed [-hnV][-e<script>][-f<script文件>][文本文件]
注:
1、注意sed以及后面选项,sed命令和输入文件,每个元素之间都至少有一个空格。 
2、sed -commands(sed命令)是sed内置的一些命令选项,为了和前面的options(选项)区分,故称为sed命令 
3、sed -commands 既可以是单个sed命令,也可以是多个sed命令组合。使用的时候加上 单or双引号
4、input -file (输入文件)是可选项,sed还能够从标准输入如管道获取输入。
---------------------------------------------------------------------
参数(选项)说明:
-e<script>或--expression=<script> 以选项中指定的script来处理输入的文本文件。即:一行命令语句可以执行多条sed命令
-f<script文件>或--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。
-h或--help 显示帮助。
-n或--quiet或--silent 仅显示script处理后的结果。即:取消默认的sed的输出,常与sed命令的p连用。不输出模式空间的内容
--version 显示版本信息。
-r 使用扩展正则表达式,默认情况sed只识别基本正则表达式。+ | ?
-i 直接修改文件内容,而不是输出到终端,如果不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件
---------------------------------------------------------------------
sed命令说明:
a (append):追加操作。即:在指定行后添加一行或多行文本(追加文本到指定行后)
c (change):取代指定的行
d (delete):删除指定的行
i (insert):插入操作。即:在指定行前添加一行或多行文本(插入文本到指定行前)
p ( print):打印模式空间内容,通常p会与选项-n一起使用
!         :取反操作。即:对指定行以外的所有行应用命令
---------------------------------------------------------------------
原理说明:
sed读取一行,首先将这行放入到缓存中。然后才对这行进行处理。完成以后,将缓冲区的内容发送到终端(屏幕)。
存储sed读取到的内容的缓存区空间称之为:模式空间(Pattern Space)

下面详细介绍sed命令的增删改查操作:
注:下面的命令使用只要不加 -i操作,都是随意操作文件的(并不实质修改文件内容)。

sed增加

这里我们需要用到上面的2个sed命令,分别是:a 和 i

[root@localhost shell_study]# cat test.txt 
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
[root@localhost shell_study]# sed "9a Hello,I am Songbaobao" test.txt 
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
Hello,I am Songbaobao                         #只是看到了这个效果
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost shell_study]# cat test.txt 
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
[root@localhost shell_study]# 
--------------------------------------------------------------
[root@localhost shell_study]# sed "9a Hello,I am Songbaobao" test.txt 
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
Hello,I am Songbaobao                #这是原第九行的后面追加
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost shell_study]# sed "10i Hello,I am Songbaobao" test.txt 
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
Hello,I am Songbaobao                #这是原第十行的前面插入
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost shell_study]# 
--------------------------------------------------------------
[root@localhost shell_study]# 下面是支持 $  表示最后一行
[root@localhost shell_study]# sed "$a Hello,I am Songbaobao" test.txt 
sed: -e expression #1, char 3: extra characters after command
[root@localhost shell_study]# sed '$a Hello,I am Songbaobao' test.txt 
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
Hello,I am Songbaobao               #这是原最后一行的后面追加
[root@localhost shell_study]# 
[root@localhost shell_study]# sed '$i Hello,I am Songbaobao' test.txt 
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
Hello,I am Songbaobao              #这是原最后一行的前面插入
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost shell_study]#
--------------------------------------------------------------
[root@localhost shell_study]# 下面表示的是多行的插入
[root@localhost shell_study]# sed '$a Hello,I am Songbaobao\nTsinghua\nPekingUniversity\nZhejiangUniversity' test.txt 
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
Hello,I am Songbaobao     #这是原最后一行的后面追加  多行内容
Tsinghua
PekingUniversity
ZhejiangUniversity
[root@localhost shell_study]#

sed删除

这里我们需要用到上面的sed命令是:d 。同上:sed可以对单行或多行文本进行处理。若是在sed命令前面不指定地址范围,那么默认会匹配所有行。

[root@localhost shell_study]# sed 'd' test.txt 
[root@localhost shell_study]# cat test.txt 
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
[root@localhost shell_study]# 下面是删除第一行
[root@localhost shell_study]# sed '1d' test.txt 
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
[root@localhost shell_study]# 下面是删除1到5行
[root@localhost shell_study]# sed '1,5d' test.txt 
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
[root@localhost shell_study]# 下面是删除匹配到的行
[root@localhost shell_study]# sed '/^root/d' test.txt 匹配root开头的行
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
[root@localhost shell_study]# sed '/root/d' test.txt 匹配到root的行
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
[root@localhost shell_study]#

注:如上,在sed使用正则的格式和awk一样,使用2个”/“包含指定的正则表达式,即“/正则表达式/”。

[root@localhost shell_study]# sed '2,$d' test.txt  从第2行开始删完
root:x:0:0:root:/root:/bin/bash
----------------------------------------------------------------
[root@localhost shell_study]# 下面是sed的取反 ! 的使用
[root@localhost shell_study]# 下面是删除除 1 2行的
[root@localhost shell_study]# sed '1,2!d' test.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost shell_study]# 

sed修改

这里我们需要用到上面的sed命令是:c 。即:change,意思是替换

[root@localhost shell_study]# sed '1c Hello,I am Songbaobao' test.txt 
Hello,I am Songbaobao  #修改替换的是第一行
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
[root@localhost shell_study]#

下面是文本替换:(将root全部替换成songbaobao
这里用到的sed命令,其中的选项如下:

  • “s”:单独使用–>将每一行中第一处匹配的字符串进行替换==>sed命令
  • “g”:每一行进行全部替换–>sed命令 s的替换标志之一(全局替换global),非sed命令。
  • “-i”:修改文件内容==>sed的选项,注意和sed命令i区别。(不加 -i 就不修改文件的实际内容)
[root@localhost myshell]# cat test.txt 
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
[root@localhost myshell]# sed 's/root/songbaobao/' test.txt #不加g标志
songbaobao: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:/songbaobao:/sbin/nologin# 只替换了每一行的第一个匹配内容
[root@localhost myshell]# sed 's/root/songbaobao/g' test.txt #加g标志
songbaobao:x:0:0:songbaobao:/songbaobao:/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:/songbaobao:/sbin/nologin# 替换了每一行的全部 匹配内容
[root@localhost myshell]#
[root@localhost myshell]# sed '/^root/{s/root/songbaobao/g}' test.txt 
songbaobao:x:0:0:songbaobao:/songbaobao:/bin/bash#只替换了以root开头的行的全部 匹配内容
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
[root@localhost myshell]# sed '/^root/{s/root/songbaobao/}' test.txt 
songbaobao:x:0:0:root:/root:/bin/bash#只替换了以root开头的行的第一个 匹配内容
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
[root@localhost myshell]# 
#-------------------------------------------------------------------------
[root@localhost myshell]# cp /etc/sysconfig/selinux ./linux.txt
[root@localhost myshell]# ls
linux.txt  test.txt
[root@localhost myshell]# cat linux.txt 

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted 


[root@localhost myshell]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' linux.txt 
[root@localhost myshell]# cat linux.txt 

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted 


[root@localhost myshell]# 下面将使用上 分组 \1进行调用;-r为扩展正则
[root@localhost myshell]# sed -i -r 's/(SELINUX=)disabled/\1enforcing/' linux.txt 
[root@localhost myshell]# cat linux.txt 

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted 


[root@localhost myshell]# 

sed查询

这里我们需要用到上面的sed命令是:“p”。即:输出指定内容,但默认会输出2次匹配的结果,因此使用-n选项取消默认输出:print。

相较于之前最常用的是cat或more或less命令等,sed就能查看指定的行 。而且我们前面也说过使用sed比其他命令vim等读取速度更快!

[root@localhost myshell]# cat test.txt 
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
[root@localhost myshell]# sed '2p' test.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin #第二行被多打印了一遍
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
[root@localhost myshell]# 可是我不想看到重复的这一行,即:只想要这个 第二行。如下:
[root@localhost myshell]# sed -n '2p' test.txt 
bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost myshell]# 打印多行,如下:
[root@localhost myshell]# sed -n '2,5p' test.txt #若是不加-n
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
[root@localhost myshell]# #若是不加-n
[root@localhost myshell]# sed  '2,5p' test.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/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
[root@localhost myshell]#
#-------------------------------------------------------------------------
[root@localhost myshell]# sed -n '/root/p' test.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost myshell]#

注:在使用上面的p的时候 不要同 -i 进行混合使用。具体原因如下:

[root@localhost myshell]# sed -n '2p' test1.txt 
bin:x:1:1:bin:/bin:/sbin/nologin  #只把第二行打印出来了
[root@localhost myshell]# cat test1.txt 
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
[root@localhost myshell]# sed -ni '2p' test1.txt 
[root@localhost myshell]# cat test1.txt 
bin:x:1:1:bin:/bin:/sbin/nologin #-i 把第二行给写到原文件里面了 
[root@localhost myshell]#

下面是加上 -e,执行的多点操作:

[root@localhost myshell]# cat test.txt 
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
[root@localhost myshell]# sed -e "1d" -e "3d" -e "5d" test.txt  删除1 3 5行
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/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
[root@localhost myshell]#  sed -n -e '2p' -e '5p' test.txt  只查2 5行
bin:x:1:1:bin:/bin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost myshell]#

下面展示一下 怎么删除注释行和空白行:

[root@localhost myshell]# ls
test.txt
[root@localhost myshell]# vim test.txt 
[root@localhost myshell]# cat test.txt 
#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
[root@localhost myshell]#  sed -e '/^#/d' -e '/^$/d' test.txt 
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
[root@localhost myshell]#下面展示 第二种方式:grep
#---------------------------------------------------------------
[root@localhost myshell]# cat test.txt 
#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
[root@localhost myshell]# grep -E "(^#)|(^$)" test.txt 拿到要删除的行
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin


[root@localhost myshell]# grep -E -v "(^#)|(^$)" test.txt 取反
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
[root@localhost myshell]# grep -E -v "(^#)|(^$)" test.txt >test1.txt
[root@localhost myshell]# cat test1.txt 
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
[root@localhost myshell]#

sed命令 小结

  1. 查找指定的字符串
# 显示文件中保含root的行(显示模式空间中的内容)
[root@localhost myshell]# cat test.txt 
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
[root@localhost myshell]# sed -n '/root/p' test.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost myshell]#
  1. 在指定的位置做增删
[root@localhost myshell]# sed '/^root/d' test.txt  删除以root为开头的行
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
[root@localhost myshell]#  sed '/root/a I am Songbabaobao' test.txt 在包含root的行后添加一行
root:x:0:0:root:/root:/bin/bash
I am Songbabaobao
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
I am Songbabaobao
[root@localhost myshell]#
  1. 按行替换(将5到9行的内容替换为I am Songbaobao)
[root@localhost myshell]# sed '5,9c I am Songbaobao' test.txt 
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
I am Songbaobao
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost myshell]#
  1. 按照字符替换(上面已经展示过了:将/etc/selinux/config中的SELINUX=disabled改成 enforcing)
# sed -i 's/SELINUX=disabled/SELINUX=enforcing/g' 文件
# sed -r -i 's/(SELINUX=)disabled/\1enforcing/g'  文件
  1. 查找指定的内容再做替换
# 将以r开头的行中的oo替换为666
[root@localhost myshell]# cat test.txt 
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
[root@localhost myshell]# sed '/^r/{s/oo/666/g}' test.txt #找到匹配行,做替换
r666t:x:0:0:r666t:/r666t:/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
[root@localhost myshell]# 
  1. 多点编辑
    上面的删除#注释行和空白行
sed -e '/^#/d' -e '/^$/d' test.txt 
grep -E -v "(^#)|(^$)" test.txt >test1.txt
  1. 取反操作
# 显示非1-3行
[root@localhost myshell]# sed -n '1,3!p' test.txt 
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
[root@localhost myshell]#

awk命令

awk详解

awk详解

awk不仅仅是linux系统中的一个命令,而且是一种编程语言:可以用来处理数据和生成报告(excel)。处理的数据可以是一个或多个文件,可以是来自标准输入,也可以通过管道获取标准输入,awk可以在命令行上直接编辑命令进行操作,也可以编写成awk程序来进行更为复杂的运用

awk 命令
---------------------------------------------------------------------
语法格式如下:
1. awk 命令由模式,动作,或者模式和动作的组合组成。
2. pattern 类似模式匹配(理解为条件),可由表达式组成;亦可 / 正则表达式 /。
3. action 由{语句1;语句2;---}
---------------------------------------------------------------------
使用格式如下:
awk 【options(awk参数)】 'pattern(模式,即条件) {action}(动作,即找到之后干啥)' test.txt
注:awk 命令后面处理的内容的来源:标准输入、一个或多个文本文件、管道
---------------------------------------------------------------------
参数说明如下:
-F:指定分隔符
---------------------------------------------------------------------
常见概念如下:
4. record:一行就是一个记录
5. field separator:进行对记录进行切割的时候所使用的字符
6. field:将一条记录分割成的每一段 为字段
7. filename:当前处理文件的文件名
8. FS(Field Separator):字段分隔符(默认是以空格为分隔符)
9. NR(Number of Record):记录的编号(awk每读取一行,NR就加1)
10. NF(Number of Field):字段数量(记录了当前这条记录包含多少个字段)
11. ORS(Output Record Separator):指定输出记录分隔符(指定在输出结果中记录末尾是什么,默认是\n,也就是换行)
12. OFS(Output Field Separator):输出字段分隔符
13. RS:记录分隔符

下面看一下特殊的 $ 输出字段的表示:(对应字段的输出

$1 输出第一个字段
$2 输出第二个字段
$NF 输出最后一个字段
$0 输出整个记录
awk简单使用

下面主要是看一下awk命令的具体实例,其工作背景如下:

[root@localhost myshell]# cat test.txt 
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
[root@localhost myshell]# 

显示第2到5行的每条记录,如下

[root@localhost myshell]# awk 'NR>=2&&NR<=5{print $0}' test.txt 
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
[root@localhost myshell]#

如上:模式(条件)就是NR>=2&&NR<=5 ;后面的{} 自然就是匹配成功之后的动作(干啥)。也就是说:awk开始处理test.txt文件 读取第一行(NR=1 不满足条件);接下来再读取一行 NR=2(直到5都是满足的)满足一行 就执行后面的动作一次。直到6 7 8 9 最后一行(End Of File)。
显示全文,并前面有行号,如下

[root@localhost myshell]# awk '{print NR,$0}' test.txt 
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost myshell]#

显示全文每条记录的bash类型,如下
注:那也就是要打印 每条记录 :分开的最后一列

[root@localhost myshell]# awk -F ":" '{print NR,$7}' test.txt 
1 /bin/bash
2 /sbin/nologin
3 /sbin/nologin
4 /sbin/nologin
5 /sbin/nologin
6 /bin/sync
7 /sbin/shutdown
8 /sbin/halt
9 /sbin/nologin
10 /sbin/nologin
[root@localhost myshell]# awk -F ":" '{print NR,$NF}' test.txt 
1 /bin/bash
2 /sbin/nologin
3 /sbin/nologin
4 /sbin/nologin
5 /sbin/nologin
6 /bin/sync
7 /sbin/shutdown
8 /sbin/halt
9 /sbin/nologin
10 /sbin/nologin
[root@localhost myshell]# 

输出有大于5个字段的行的第三个字段,如下
注:现在test.txt里面 每个记录的字段数都大于5 预收相当于把全文的第三个字段都打印出来了

[root@localhost myshell]# awk -F ":" 'NF>5{print NR,$3}' test.txt 
1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8
10 11
[root@localhost myshell]#

输出每行行号和该行有几个字段,如下

[root@localhost myshell]# awk -F ":" '{print NR,NF}' test.txt 
1 7
2 7
3 7
4 7
5 7
6 7
7 7
8 7
9 7
10 7
[root@localhost myshell]#

awk正则表达式

awk正则表达式

工作的背景内容同上。我们上面也说过了awk支持 基础正则表达式和扩展正则表达式:

简单地使用正则表达式的例子,如下

[root@localhost myshell]# free -h
              total        used        free      shared  buff/cache   available
Mem:           2.9G        275M        2.3G        9.1M        355M        2.4G
Swap:          2.0G          0B        2.0G
[root@localhost myshell]# free -m
              total        used        free      shared  buff/cache   available
Mem:           3018         276        2386           9         355        2477
Swap:          2047           0        2047
[root@localhost myshell]# free -h | awk -F "G" 'NR==2{print $2}'
        276M        2.3
[root@localhost myshell]# free -h | awk -F "G" 'NR==2{print $2}' | awk -F "M" '{print $2}'
        2.3
[root@localhost myshell]# free -h | awk -F " +" 'NR==2{print $4}'
2.3G
[root@localhost myshell]# free -m | awk -F " +" 'NR==2{print $4}'
2386
[root@localhost myshell]#

使用正则表达式 匹配整行,如下

[root@localhost myshell]# awk '/^root/' test.txt 
root:x:0:0:root:/root:/bin/bash
[root@localhost myshell]# awk '/^root/{print $0}' test.txt 
root:x:0:0:root:/root:/bin/bash
[root@localhost myshell]# awk '$0~/^root/' test.txt 整行后面使用正则表达式
root:x:0:0:root:/root:/bin/bash
[root@localhost myshell]# awk '$0~/^root/{print $0}' test.txt 
root:x:0:0:root:/root:/bin/bash
[root@localhost myshell]#

注:awk只用正则表达式的时候是默认匹配整行的,即‘$0~/^root/’ 和 ‘/^root/’是一样的。

使用正则表达式 匹配某一列,如下

[root@localhost myshell]# awk -F ":" '$5~/root/' test.txt 
root:x:0:0:root:/root:/bin/bash
[root@localhost myshell]# awk -F ":" '$5~/root/{print $0}' test.txt 
root:x:0:0:root:/root:/bin/bash
[root@localhost myshell]# 

注释上面:

  1. $5表示第五个区域(列)
  2. ~表示匹配(正则表达式匹配)
  3. /root/表示匹配root这个字符串
  4. $5~/root/表示第五个区域(列)匹配正则表达式/root/。即:第5列包含root这个字符串,则显示这一行。

使用正则表达式 匹配行尾为shutdown,如下

[root@localhost myshell]# awk '/shutdown$/{print $0}' test.txt 
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
[root@localhost myshell]# awk -F ":" '/shutdown$/{print $0}' test.txt 
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
[root@localhost myshell]#

显示名字和登录类型,如下

[root@localhost myshell]# awk -F ":" '{print $1,$NF}' test.txt 
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
operator /sbin/nologin
[root@localhost myshell]#

awk的特殊模式

awk BEGIN&END模式

awk的两种特殊模式:

  1. BEGIN 模块在awk命令执行之前(读取文件)就执行,它主要是来定义 内置变量(预定义变量,例如:FS RS)。换言之:BEGIN模块是最先执行的(就是BEGIN后面的动作{ action }) 。awk必须在输入文件进行任何处理前先执行BEGIN里的动作(action)。我们可以不要任何输入文件,就可以对BEGIN模块进行测试,因为awk需要先执行完BEGIN模式,才对输入文件做处理。因此BEGIN模式常常被用来修改内置变量ORS,RS,FS,OFS等值。
  2. 而EHD模块是在awk读取完所有的文件的时候,再执行END模块(awk全部执行完 才执行END)。一般用来输出一个结果(如:累加,数组结果),也可以是和BEGIN模块类似的结尾标识信息。与BEGIN模式相对应的END模式,格式一样,但是END模式仅在awk处理完所有输入行后才进行处理。
[root@localhost myshell]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:4e:a9:01 brd ff:ff:ff:ff:ff:ff
    inet 192.29.0.51/23 brd 192.29.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::9269:9004:6205:f3b7/64 scope link 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
    link/ether 52:54:00:fe:41:90 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 1000
    link/ether 52:54:00:fe:41:90 brd ff:ff:ff:ff:ff:ff
[root@localhost myshell]# ip a | awk '/global virbr0/{print $0}'
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
[root@localhost myshell]# ip a | awk '/global virbr0/{print $0}' | awk -F "( +)|/" '{print $3}'
192.168.122.1
[root@localhost myshell]# ip a | awk '/global virbr0/{print $0}' | awk 'BEGIN{FS="( +)|/"}{print $3}'
192.168.122.1
[root@localhost myshell]#

如上:使用BEGIN模块预定义了 分隔符。

[root@localhost myshell]# cat test.txt | awk '{print NR,$0}END{print "Hello,I am Songbaobao"}'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
Hello,I am Songbaobao
[root@localhost myshell]# awk -F ':' 'BEGIN{print "user_name","bash_type"}{print $1,$NF}END{print "Hello,I am Songbaobao"}' test.txt 
user_name bash_type
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
operator /sbin/nologin
Hello,I am Songbaobao
[root@localhost myshell]#

统计包含root的行的数量,如下

[root@localhost myshell]# cat test.txt  | grep root | wc -l
2
[root@localhost myshell]# cat test.txt  | grep -c root
2
[root@localhost myshell]# cat test.txt  | awk 'BEGIN{i=0}/root/{i++}END{print i}'
2
[root@localhost myshell]# cat test.txt  | awk '/root/{i++}END{print i}'
2
[root@localhost myshell]#

因此,带有BEGIN END模块的awk执行过程(命令结构),如下:
在这里插入图片描述

awk 'BEGIN{commands}/pattern/{commands}END{commands}' test.txt

awk数组的使用

awk数组
awk 数组结构如下:
----------------------------------------------------
数组名【元素名】=值
array_name[element_name]=value

awk数组完成的任务 我们也可以使用cut sort unique来实现。当然使用awk相对来说,更加的简洁易懂。下面看一下awk数组使用:
统计域名出现的次数,如下
注:这个我们已经在第一节的时候,已经通过使用命令来实现过了。背景如下:

[root@localhost myshell]# vim test.txt
[root@localhost myshell]# cat test.txt 
http://www.baidu.com
http://www.baidu.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.sina.com
http://www.baidu.com
http://www.baidu.com
http://www.baidu.com
http://www.qq.com
http://www.qq.com
http://www.qq.com
http://www.qq.com
http://www.qq.com
http://www.qq.com
http://www.baidu.com
http://www.baidu.com
http://www.baidu.com
http://www.baidu.com
http://www.baidu.com
http://www.baidu.com
http://www.taobao.com
http://www.taobao.com
http://www.taobao.com
http://www.taobao.com
http://www.taobao.com
http://www.taobao.com
http://www.baidu.com
http://www.baidu.com
http://www.baidu.com
http://www.baidu.com
http://www.baidu.com
[root@localhost myshell]#

实现如下:

[root@localhost myshell]# cat test.txt | awk -F "/+" '{array[$2]++}END{for (i in array) print i,array[i]}'
www.sina.com 12
www.qq.com 6
www.taobao.com 6
www.baidu.com 16
[root@localhost myshell]#

awk命令 小结

背景同上!

  1. 结合内置变量,打印指定的几行,以及字段数量
# 输出有大于5个字段的行的第三个字段
[root@localhost myshell]# cat test1.txt | awk -F ":" 'NF>=5{print $3}'
0
1
2
3
4
5
6
7
8
11
# 输出每行行号和该行有几个字段
[root@localhost myshell]# cat test1.txt | awk -F ":" '{print NR,NF}'
1 7
2 7
3 7
4 7
5 7
6 7
7 7
8 7
9 7
10 7
# 输出用户名,要求所有用户显示在同一行,而且用空格分隔
[root@localhost myshell]# cat test1.txt | awk 'BEGIN{FS=":"; ORS=" "}{print $1}'
root bin daemon adm lp sync shutdown halt mail operator [root@localhost myshell]#
  1. 结合正则来匹配一行或者某个字段
# 输出用户名以s为开头的用户的uid
[root@localhost myshell]# cat test1.txt | awk -F ":" '/^s/{print $3}'
5
6
# 输出第五个字段是以t为结尾的用户的姓名
[root@localhost myshell]# cat test1.txt | awk -F ":" '$5~/t$/{print $1}'
root
halt
  1. 采用比较符号来进行打印指定的某些行
# 实现仅仅输出3-5的内容,每行前面添加一个行号
[root@localhost myshell]# cat test1.txt | awk 'NR>=3&&NR<=5{print NR,$1}'
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost myshell]# cat test1.txt | awk 'NR==3,NR==5{print NR,$1}'
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# 实现仅仅输出3 和 5 和 7行的内容,每行前面添加一个行号
[root@localhost myshell]# cat test1.txt | awk 'NR==3||NR==5||NR==7{print NR,$1}'
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

下面的背景如下:

[root@localhost myshell]# cat test1.txt 
#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:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:/sbin/nologin
[root@localhost myshell]#
  1. END
# 统计mypwd中以#开头的行有多少行
[root@localhost myshell]# cat test1.txt | awk 'BEGIN{n=0}/^#/{n+=1}END{print n}'
3
# 以:为分隔符,字段数量在5-8的行的数目
[root@localhost myshell]# cat test1.txt | awk 'BEGIN{FS=":"}NF>=5&&NF<=8{n+=1}END{print n}'
9

注:awk的学习 也可以参见这篇写的很好的博客
awk 用法(使用入门)

2020年3月30日18:31:44

猜你喜欢

转载自blog.csdn.net/weixin_43949535/article/details/105003869