Linux通配符

一、Linux通配符

1.1 通配符

就是键盘上的一些特殊字符,可以实现特殊的功能,例如模糊搜索一些文件。

文件名 通配符 模糊匹配
luffy * luffyalex
luffychao
luffycunzhang
oldboy ? oldboy1
oldboy2
oldboyz
oldboyx

利用通配符可以更轻松的处理字符信息

常见通配符

符号 作用
* 匹配任意,0或多个字符,字符串
? 匹配任意1个字符,有且只有一个字符
符号集合 匹配一堆字符或文本
[abcd] 匹配abcd中任意一个字符,abcd也可以是不连续任意字符
[a-z] 匹配a到z之间任意一个字符,要求连续字符,也可以连续数字,匹配[1-9]
[!abcd] 不匹配括号中任意一个字符,也可以书写[!a-d],同于写法
[^abcd] 同上,!可以换成 ^

特殊通配符

符号 作用
[[:upper:]] 所有大写字母
[[:lower:]] 所有小写字母
[[:alpha:]] 所有字母
[[:digit:]] 所有数字
[[:alnum:]] 所有的字母和数字
[[:space:]] 所有的空白字符
[[:punct:]] 所有标点符号

案例

1.找出根目录下最大文件夹深度是3,且所有以l开头的文件,且以小写字母结尾,中间出现任意一个字符的文本文件,
[root@chaogelinux luffy_data]# find / -maxdepth 3 -type f -name "l?[[:lower:]]"
/usr/bin/ldd
/usr/bin/lua
/usr/sbin/lvm
/usr/sbin/lid

2.找出/tmp下以任意一位数字开头,且以非数字结尾的文件
[root@chaogelinux luffy_data]# find /tmp  -type f -name '[0-9][^0-9]'

3.显示/tmp下以非字母开头,后面跟着一个字母以及其他任意长度的字符的文件
[root@chaogelinux luffy_data]# find /tmp -type f -name "[^a-zA-Z][a-z]*"

4.mv/tmp/下,所有以非字母开头的文件,复制到/tmp/allNum/目录下
[root@chaogelinux luffy_data]# mv /tmp/[^a-zA-Z]* /tmp/allNum/

5.复制/tmp目录下所有的.txt文件结尾的文件,且以y、t开头的文件,放入/data目录
[root@chaogelinux tmp]# cp -r /tmp/[y,t]*.txt /data/

*号

准备数据如下

[root@pylinux tmp]# ls
chaoge.sh  chaoge.txt  oldboy.txt  oldgirl.txt  oldluffy.txt  yu.sh

1.匹配所有的txt文本

[root@pylinux tmp]# ls
chaoge.sh  chaoge.txt  oldboy.txt  oldgirl.txt  oldluffy.txt  yu.sh

2.匹配所有的sh脚本

[root@pylinux tmp]# ls *.sh
chaoge.sh  yu.sh

3.查看所有的old开头的文件

[root@pylinux tmp]# ls old*
oldboy.txt  oldgirl.txt  oldluffy.txt

?号

1.匹配一个任意字符

[root@pylinux tmp]# ls *.s?
chaoge.sh  yu.sh

2.匹配两个,三个任意字符

[root@pylinux tmp]# ls old???.txt
oldboy.txt
[root@pylinux tmp]# ls old????.txt
oldgirl.txt

[abc]

1.匹配[abc]中的一个字符

[root@pylinux tmp]# ls
a.txt  b.txt  chaoge.sh  chaoge.txt  l.txt  oldboy.txt  oldgirl.txt  oldluffy.txt  yu.sh

[root@pylinux tmp]# ls [abc].txt
a.txt  b.txt

2.匹配如下类型文件

olda*.txt oldb*.txt oldc*.txt

[root@pylinux tmp]# ls old[abcd]*.txt
oldboy.txt

[a-z]作用

[]中括号里面的a-z,表示从a到z之间的任意一个字符,a-z要连续,也可以用连续的数字,如[1-9]

img

[!abcd]

 [^abcd]  
 [^a-d]
效果同上

除了abcd四个字符以外的任意一个字符

img

img

结合find命令使用

[root@pylinux tmp]# find /tmp  -type f  -name "[a-z].txt"        #找出a到z之间单个字符的文件
/tmp/b.txt
/tmp/e.txt
/tmp/a.txt
/tmp/l.txt
/tmp/d.txt
/tmp/c.txt

[root@pylinux tmp]# find /tmp  -type f  -name "[!a-d].txt"        #找出除了a到d之间单个字符的文件
/tmp/e.txt
/tmp/2.txt
/tmp/1.txt
/tmp/l.txt

[root@pylinux tmp]# find /tmp  -type f  -name "?.txt"            #找出所有单个字符的文件
/tmp/b.txt
/tmp/e.txt
/tmp/2.txt
/tmp/a.txt
/tmp/1.txt
/tmp/l.txt
/tmp/d.txt
/tmp/c.txt

[root@pylinux tmp]# find /tmp  -type f  -name "*.txt"            #找出所有的txt文本

1.2 Linux特殊符号

路径相关

符号 作用
~ 当前登录用户的家目录
- 上一次工作路径
. 当前工作路径,或隐藏文件 .chaoge.txt
.. 上一级目录

波浪线案例

[root@pylinux tmp]# cd ~
[root@pylinux ~]# pwd
/root

[yu@pylinux ~]$
[yu@pylinux ~]$ pwd
/home/yu

短横杠案例

[root@pylinux opt]# cd /tmp
[root@pylinux tmp]# cd -
/opt
[root@pylinux opt]# cd -
/tmp

[root@pylinux tmp]# echo $OLDPWD
/opt

点案例

[root@pylinux tmp]# find .  -name "*.sh"
./yu.sh
./chaoge.sh

点点案例

[root@pylinux tmp]# mkdir ../opt/超哥nb
[root@pylinux tmp]#
[root@pylinux tmp]# ls /opt/
超哥nb

[root@pylinux home]# ls -a
.  ..  py  testyu  yu

特殊引号

在linux系统中,单引号、双引号可以用于表示字符串

名称 解释
单引号 '' 所见即所得,强引用,单引号中内容会原样输出
双引号 "" 弱引用,能够识别各种特殊符号、变量、转义符等,解析后再输出结果
没有引号 一般连续字符串、数字、路径可以省略双引号,遇见特殊字符,空格、变量等,必须加上双引号
反引号 `` 常用于引用命令结果,同于$(命令)

反引号案例

用反引号进行命令解析

[root@pylinux tmp]# date +%F
2019-11-05
[root@pylinux tmp]# touch `date +%F`.txt    #创建文件,名字是当前时间格式
[root@pylinux tmp]# ls
2019-11-05.txt

[root@pylinux tmp]# echo date
date
[root@pylinux tmp]# echo `date`        #反引号中命令会被执行
2019年 11月 05日 星期二 16:29:28 CST

[root@pylinux tmp]# which cat
/usr/bin/cat
[root@pylinux tmp]#
[root@pylinux tmp]# ls -l `which cat`        #反引号中命令被执行
-rwxr-xr-x. 1 root root 54080 4月  11 2018 /usr/bin/cat

双引号案例

当输出双引号内所有内容时,内容中有命令需要用反引号标记

[root@pylinux tmp]# echo "date"
date
[root@pylinux tmp]#
[root@pylinux tmp]#
[root@pylinux tmp]# echo "`date`"
2019年 11月 05日 星期二 16:30:42 CST

[root@pylinux tmp]# echo "今天是星期 `date +%w`"
今天是星期 2

[root@pylinux tmp]# echo "今年是$(date +%Y)年"
今年是2019年

单引号案例

单引号中内容是强引用,保持原样输出

[root@pylinux tmp]# echo "今天日期是 `date +%F`"        #双引号可以
今天日期是 2019-11-05

[root@pylinux tmp]# echo '今天日期是 `date +%F`'        #单引号不可以
今天日期是 `date +%F`

无引用案例

没有引号,很难确定字符串的边界,且linux命令是以空格区分的

建议用双引号代替不加引号

[root@pylinux tmp]# echo "今天是 `date +%Y`年"
今天是 2019年

[root@pylinux tmp]# echo 今天是 `date +%Y`年
今天是 2019年

[root@pylinux tmp]# ls "/tmp"
2019-11-05.txt
[root@pylinux tmp]#
[root@pylinux tmp]# ls /tmp
2019-11-05.txt

1.3 输出重定向特殊符号

输入设备

  • 键盘输入数据
  • 文件数据导入

输出设备

  • 显示器、屏幕终端
  • 文件

数据流

程序的数据流:

  • 输入流:<---标准输入 (stdin),键盘
  • 输出流:-->标准输出(stdout),显示器,终端
  • 错误输出流:-->错误输出(stderr)

文件描述符

在Linux系统中,一切设备都看作文件。

而每打开一个文件,就有一个代表该打开文件的文件描述符。

程序启动时默认打开三个I/O设备文件:

  • 标准输入文件stdin,文件描述符0
  • 标准输出文件stdout,文件描述符1
  • 标准错误输出文件stderr,文件描述符2
符号 特殊符号 简介
标准输入stdin 代码为0,配合< 或<< 数据流从右向左 👈
标准输出stdout 代码1,配合>或>> 数据从左向右👉
标准错误stderr 代码2,配合>或>> 数据从左向右👉
重定向符号 数据流是箭头方向
标准输入重定向 0< 或 < 数据一般从文件流向处理命令
追加输入重定向 0<<或<< 数据一般从文件流向处理命令
标准输出重定向 1>或> 正常输出重定向给文件,默认覆盖
标准输出追加重定向 1>>或>> 内容追加重定向到文件底部,追加
标准错误输出重定向 2> 讲标准错误内容重定向到文件,默认覆盖
标准错误输出追加重定向 2>> 标准错误内容追加到文件底部

错误输出

[root@chaogelinux tmp]# ls yyy
ls: 无法访问yyy: 没有那个文件或目录
[root@chaogelinux tmp]#
[root@chaogelinux tmp]# ls yyy > cuowu.txt
ls: 无法访问yyy: 没有那个文件或目录
[root@chaogelinux tmp]# ls yyy >> cuowu.txt
ls: 无法访问yyy: 没有那个文件或目录
[root@chaogelinux tmp]# ls yyy 2> cuowu.txt
[root@chaogelinux tmp]#
[root@chaogelinux tmp]#
[root@chaogelinux tmp]# cat cuowu.txt
ls: 无法访问yyy: 没有那个文件或目录

特殊重定向,合并重定向

  • 2>&1把标准错误,重定向到标准输出

把命令的执行结果写入文件,标准错误当做标准输出处理,也写入文件

  • Command > /path/file 2>&1
echo "I am oldboy" 1>>oldboy.txt 2>>oldboy.txt

echo  "I am oldboy"  >> /dev/null 2>&1            #  命令已经将结果重定向到/dev/null,2>&1符号也会将标准错误输出到/dev/null,/dev/null是一个黑洞,只写文件

输入重定向

数据流输入

[root@chaogelinux tmp]# cat < yu2.txt
我是 yu2,你是谁,想偷看我?

#mysql数据导入
mysql -uroot -p < db.sql

[root@chaogelinux ~]# cat chaoge.txt
a b c d e f g
[root@chaogelinux ~]# tr -d 'a-c' < chaoge.txt
   d e f g

[root@chaogelinux ~]# wc -l < chaoge.txt
1

其他特殊符号

符号 解释
; 分号,命令分隔符或是结束符
# 1.文件中注释的内容 2.root身份提示符
| 管道符,传递命令结果给下一个命令
$ 1.变量,取出变量的值 2.普通用户身份提示符
\ 转义符,将特殊含义的字符还原成普通字符
{} 1.生成序列 2.引用变量作为变量与普通字符的分割

;号

  • 表示命令的结束
  • 命令间的分隔符
  • 配置文件的注释符
[root@pylinux tmp]# pwd;ls            #执行两条命令
/tmp
2019-11-05.txt  oldboy.txt  txt

#号

  • 注释行
# nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

|号

比如生活中的管道,能够传输物质

Linux管道符 | 用于传输数据,对linux命令的处理结果再次处理,直到得到最终结果

[root@pylinux ~]# ifconfig |grep inet
        inet 10.141.32.137  netmask 255.255.192.0  broadcast 10.141.63.255
        inet 127.0.0.1  netmask 255.0.0.0

[root@pylinux tmp]# ls | grep .txt
2019-11-05.txt
oldboy.txt

[root@pylinux tmp]# netstat -tunlp|grep 22
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1401/sshd


[root@pylinux tmp]# netstat -tunlp|grep 3306

[root@pylinux tmp]# netstat -tunlp|grep 80

[root@pylinux tmp]# ps aux|grep python

[root@pylinux tmp]# ps aux|grep mariadb

能一次出结果的命令,尽量不要二次过滤,效率并不高

ifconfig工具被用来查看和配置网络接口配置信息。

netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。

$符

Linux系统命令行中,字符串前加$符,代表字符串变量的值

[root@pylinux tmp]# echo OLDPWD
OLDPWD
[root@pylinux tmp]# echo $OLDPWD
/root
[root@pylinux tmp]# echo PATH
PATH
[root@pylinux tmp]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/python37/bin:/root/bin
[root@pylinux tmp]# name="学linux"
[root@pylinux tmp]# echo name
name
[root@pylinux tmp]# echo $name
学linux

{}符

1.生成序列,一连串的文本

[root@pylinux tmp]# echo {1..100}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

[root@pylinux tmp]# echo {a..i}
a b c d e f g h i

[root@pylinux tmp]# echo {i..a}
i h g f e d c b a

[root@pylinux tmp]# echo {1..9}
1 2 3 4 5 6 7 8 9

[root@pylinux tmp]# echo {o,l,d}
o l d

2.利用{}快速备份文件

[root@pylinux tmp]# cp /etc/sysconfig/network-scripts/ifcfg-eth0{,.ori}

3.将变量括起来作为变量的分隔符

[root@pylinux tmp]# echo $week
3
[root@pylinux tmp]# echo "$week_oldboy"      #输出为空,系统认为week_oldboy是整个变量

[root@pylinux tmp]# echo "${week}_oldboy"        #花括号中才会识别是变量,作了分割
3_oldboy

逻辑操作符

逻辑符既可以在linux系统中直接用,也可以在Bash脚本中用

命令 解释
&& 前一个命令成功,再执行下一个命令
|| 前一个命令失败了,再执行下一个命令
! 1.在bash中取反 2.在vim中强制性 3.历史命令中 !ls找出最近一次以ls开头的命令

&&案例

[root@pylinux tmp]# ls && cd /opt && pwd        #执行成功会继续下一个命令
2019-11-05.txt  oldboy.txt  txt
/opt

[root@pylinux opt]# ls /tmpp && cd /tmp        #执行失败就结束
ls: 无法访问/tmpp: 没有那个文件或目录

||案例

[root@pylinux opt]# ls /tmpp || cd /tmp            #执行失败才会继续下一个命令
ls: 无法访问/tmpp: 没有那个文件或目录
[root@pylinux tmp]#

[root@pylinux tmp]# cd /opt || cd /root            #执行成功则不会继续下一个命令
[root@pylinux opt]#

感叹号

  • 取反
[root@pylinux tmp]# ls [a-f]*
a  b  c  d  e  f
[root@pylinux tmp]# ls [!a-f]*        #取反的意思
2019-11-05.txt  g  h  i  j  k  l  m  n  o  oldboy.txt  p  q  r  s  t  txt  u  v  w  x  y  z
  • 感叹号的vim强制退出
  • 找出历史命令

1.4 bash

img

  • bash是一个命令处理器,运行在文本窗口中,并能执行用户直接输入的命令
  • bash还能从文件中读取linxu命令,称之为脚本
  • bash支持通配符、管道、命令替换、条件判断等逻辑控制语句

bash的特性

  • 命令行展开
[root@chaogelinux ~]# echo {tom,bob,chaoge,jerry}
tom bob chaoge jerry

[root@chaogelinux ~]# echo chaoge{666,888}
chaoge666 chaoge888

[root@chaogelinux ~]# echo chaoge{1..5}
chaoge1 chaoge2 chaoge3 chaoge4 chaoge5

[root@chaogelinux ~]# echo chaoge{1..10..2}
chaoge1 chaoge3 chaoge5 chaoge7 chaoge9

[root@chaogelinux ~]# echo chaoge{01..10..2}
chaoge01 chaoge03 chaoge05 chaoge07 chaoge09
  • 命令别名
alias,unalias
  • 命令历史
history
!行号
!! 上一次的命令
  • 快捷键
ctrl + a  移动到行首
ctrl + e  移动到行尾
ctrl + u  删除光标之前的字符
ctrl + k  删除光标之后的字符
ctrl + l  清空屏幕终端内容,同于clear
  • 命令补全
tab键
补全
    $PATH中存在的命令
  • 文件路径补全
/opt/chaoge/linux_study

二、Linux正则表达式

正则表达式:Regual Expression, REGEXP

由一类特殊字符及文本字符所编写的模式,其中有些字符不表示其字面意义,而是用于表示控制或通配的功能;

分两类:

  • 基本正则表达式:BRE
  • 扩展正则表达式:ERE

正则表达式的意义

  • 处理大量的字符串
  • 处理文本

通过特殊符号的辅助,可以让linux管理员快速过滤、替换、处理所需要的字符串、文本,让工作高效。

通常Linux运维工作,都是面临大量带有字符串的内容,如

  • 配置文件
  • 程序代码
  • 命令输出结果
  • 日志文件

且此类字符串内容,我们常会有特定的需要,查找出符合工作需要的特定的字符串,因此正则表达式就出现了

  • 正则表达式是一套规则和方法
  • 正则工作时以单位进行,一次处理一行
  • 正则表达式化繁为简,提高工作效率
  • linux仅受三剑客(sed、awk、grep)支持,其他命令无法使用

正则表达式应用非常广泛,应用在如Python、Java、Perl等,Linux下普通命令无法使用正则表达式的,只能使用三剑客。

通配符是大部分普通命令都支持的,用于查找文件或目录,而正则表达式是通过三剑客命令在文件(数据流)中过滤内容的

Linux三剑客

文本处理工具,均支持正则表达式引擎

  • grep:文本过滤工具,(模式:pattern)工具
  • sed:stream editor,流编辑器;文本编辑工具
  • awk:Linux的文本报告生成器(格式化文本),Linux上是gawk

正则表达式的分类

Linux三剑客主要分两类

  • 基本正则表达式(BRE、basic regular expression)
BRE对应元字符有 ^$.[]*
  • 扩展正则表达式(ERE、extended regular expression)
ERE在在BRE基础上,增加上 (){}?+| 等字符

基本正则表达式BRE集合

  • 匹配字符
  • 匹配次数
  • 位置锚定
符号 作用
^ 尖角号,用于模式的最左侧,如 "^oldboy",匹配以oldboy单词开头的行
$ | 美元符,用于模式的最右侧,如"oldboy$",表示以oldboy单词结尾的行
^$ 组合符,表示空行
. 匹配任意一个且只有一个字符,不能匹配空行
\ 转义字符,让特殊含义的字符,现出原形,还原本意,例如\.代表小数点
* 匹配前一个字符(连续出现)0次或1次以上 ,重复0次代表空,即匹配所有内容
.* 组合符,匹配任意长度的任意字符
^.* 组合符,匹配任意多个字符开头的内容
.*$ 组合符,匹配以任意多个字符结尾的内容
[abc] 匹配[]集合内的任意一个字符,a或b或c,可以写[a-c]
[^abc] 匹配除了后面的任意字符,a或b或c,表示对[abc]的取反
<pattern> 匹配完整的内容
<或> 定位单词的左侧,和右侧,如<chao>可以找出"The chao ge",缺找不出"yuchao"

扩展正则表达式ERE集合

扩展正则必须用 grep -E 才能生效

字符 作用
+ 匹配前一个字符1次或多次,前面字符至少出现1次
[😕]+ 匹配括号内的":"或者"/"字符1次或多次
? 匹配前一个字符0次或1次,前面字符可有可无
竖线 表示或者,同时过滤多个字符串
() 分组过滤,被括起来的内容表示一个整体
a 匹配前一个字符最少n次,最多m次
a 匹配前一个字符最少n次
a 匹配前一个字符正好n次
a 匹配前一个字符最多m次

Tip:

grep命令需要使用参数 -E即可支持正则表达式
egrep不推荐使用,使用grep -E替代
grep不加参数,得在特殊字符前面加"\"反斜杠,识别为正则

三、grep

全拼:Global search REgular expression and Print out the line.

作用:文本搜索工具,根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查,打印匹配到的行

模式:由正则表达式的元字符文本字符所编写出的过滤条件

语法:
grep [options] [pattern]  file 
命令  参数   匹配模式   文件数据
     -i:ignorecase,忽略字符的大小写;
     -o:仅显示匹配到的字符串本身;
     -v, --invert-match:显示不能被模式匹配到的行;
     -E:支持使用扩展的正则表达式元字符;
     -q, --quiet, --silent:静默模式,即不输出任何信息;

grep命令是Linux系统中最重要的命令之一,功能是从文本文件管道数据流中筛选匹配的数据,如果再配合正则表达式,功能十分强大,是Linux运维人员必备的命令

grep命令里的匹配模式就是你想要找的东西,可以是普通的文字符号,也可以是正则表达式

参数选项 解释说明
-v 排除匹配结果
-n 显示匹配行与行号
-i 不区分大小写
-c 只统计匹配的行数
-E 使用egrep命令
--color=auto 为grep过滤结果添加颜色
-w 只匹配过滤的单词
-o 只输出匹配的内容

案例

cat /etc/passwd > /tmp/test_grep.txt

grep  "login" /tmp/test_grep.txt  -n                                #找出login有关行
grep  "login" /tmp/test_grep.txt  -n -v                                 #找出没有login的行
grep   "ROOT" /tmp/test_grep.txt  -i                                      #忽略大小写,找出root有关行
grep -E  "root|sync"  /tmp/test_grep.txt --color=auto       #同时过滤出root和sync有关行
grep "login" /tmp/test_grep.txt  -c                 #统计匹配结果的行数
grep "login" /tmp/test_grep.txt   -n -o                   #只输出匹配出的内容
grep "oldboy" /tmp/test_grep.txt -w                         #完整匹配,字符串精确匹配,整个单词
grep -Ev "^#|^$"  /tmp/test_grep.txt                       #过滤掉空白和注释行

3.1 正则表达式grep实践

准备测试文件

img

^符号

1.输出所有以m开头的行

[root@pylinux data]# grep -i  -n "^m" luffy.txt        # -i忽略大小写  -n 显示仪行号
5:My qq is 877348180.
7:My name is chaoge.

img

2.输出所有以i开头的行

[root@pylinux data]# grep -i -n "^i" luffy.txt
1:I am oldboy teacher
2:I teach linux.
3:I like python.

img

$符

1.输出所有以r结尾的行

[root@pylinux data]# grep -i -n "r$" luffy.txt
1:I am oldboy teacher

img

2.输出所以以m结尾的行

[root@pylinux data]# grep -i -n "m$" luffy.txt
9:Our school website is http://oldboyedu.com

img

TIP

  • 注意在Linux平台下,所有文件的结尾都有一个$符
  • 可以用cat -A 查看文件

3.输出所有以"."结尾的行,注意用转义符

1.注意不加转义符的结果,正则里"."是匹配任意1个字符,grep把.当做正则处理了,因此把有数据的行找出来了,

[root@pylinux data]# grep -i -n ".$" luffy.txt
1:I am oldboy teacher
2:I teach linux.
3:I like python.
5:My qq is 877348180.
7:My name is chaoge.
9:Our school website is http://oldboyedu.com


2.加上转义符,当做普通的小数点过滤
[root@pylinux data]# grep -i -n "\.$" luffy.txt
2:I teach linux.
3:I like python.
5:My qq is 877348180.
7:My name is chaoge.

img

^$组合符

1.找出文件的空行,以及行号
[root@pylinux data]# grep "^$" luffy.txt  -n
4:
6:
8:
10:
11:
12:

img

.点符号

"."点表示任意一个字符,有且只有一个,不包含空行

[root@pylinux data]# grep -i -n "." luffy.txt
1:I am oldboy teacher
2:I teach linux.
3:I like python.
5:My qq is 877348180.
7:My name is chaoge.
9:Our school website is http://oldboyedu.com

img

匹配出 ".ac",找出任意一个三位字符,包含ac

[root@pylinux data]# grep -i -n ".ac" luffy.txt
1:I am oldboy teacher
2:I teach linux.

img

\转义符

1.找出文中所有的点"."

[root@pylinux data]# grep "\." luffy.txt
I teach linux.
I like python.
My qq is 877348180.
My name is chaoge.
Our school website is http://oldboyedu.com

img

*符

1.找出前一个字符0次或多次,找出文中出现"i"的0次或多次

[root@pylinux data]# grep -n "i*" luffy.txt
1:I am  teacher
2:I teach linux.
3:I like python.
4:
5:My qq is 283178231.
6:
7:My name is haoge.
8:
9:Our school website is http://www.baidu.com
10:
11:
12:

img

.*组合符

.表示任意一个字符,*表示匹配前一个字符0次或多次,因此放一起,代表匹配所有内容,以及空格

[root@pylinux data]# grep '.*' luffy.txt
I am oldboy teacher
I teach linux.
I like python.

My qq is 877348180.

My name is chaoge.

Our school website is http://oldboyedu.com

img

^.*o符

^以某字符为开头

.任意0或多个字符

.*代表匹配所有内容

o普通字符,一直到字母o结束

这种匹配相同字符到最后一个字符的特点,称之为贪婪匹配

[root@chaogelinux data]# grep "I.*o" luffy.txt
I am oldboy teacher
I like python.

[abc]中括号

中括号表达式,[abc]表示匹配中括号中任意一个字符,a或b或c,常见形式如下

  • [a-z]匹配所有小写单个字母
  • [A-Z]匹配所有单个大写字母
  • [a-zA-Z]匹配所有的单个大小写字母
  • [0-9]匹配所有单个数字
  • [a-zA-Z0-9]匹配所有数字和字母
[root@pylinux data]# grep '[a-z]' luffy.txt
I am oldboy teacher
I teach linux.
I like python.
My qq is 877348180.
My name is chaoge.
Our school website is http://oldboyedu.com

img

[root@pylinux data]# grep '[abcd]' luffy.txt
I am oldboy teacher
I teach linux.
My name is chaoge.
Our school website is http://oldboyedu.com

img

grep参数-o

使用"-o"选项,可以只显示被匹配到的关键字,而不是讲整行的内容都输出。

显示文件中有多少个字符a

[root@pylinux data]# grep -o  'a' luffy.txt |wc -l
5

wc -l 统计行数

[^abc]中括号中取反

[^abc][^a-c]这样的命令,"^"符号在中括号中第一位表示排除,就是排除字母a或b或c

出现在中括号里的尖角号表示取反

1.找出除了小写字母以外的字符

[root@pylinux data]# grep '[^a-z]' luffy.txt
I am oldboy teacher
I teach linux.
I like python.
My qq is 877348180.
My name is chaoge.
Our school website is http://oldboyedu.com

img

3.2 扩展正则表达式实践

此处使用grep -E进行实践扩展正则,egrep官网已经弃用

+号

+号表示匹配前一个字符1次或多次,必须使用grep -E 扩展正则

[root@pylinux data]# grep -E  'l+'  luffy.txt
I am oldboy teacher
I teach linux.
I like python.
Our school website is http://oldboyedu.com

img

?符

匹配前一个字符0次或1次

1.找出文件中包含gd或god的行

[root@pylinux data]# grep -E 'go?d' luffycity.txt
god            #字母o出现了一次
gd          #字母o出现了0次

|符

竖线|在正则中是或者的意思

1.找出系统中的txt文件,且名字里包含a或b的字符

[root@pylinux data]# find / -maxdepth 3  -name "*.txt" |grep -i -E "a|b"
/data/luffycity.txt
/data/luffy.txt
/test_find/chaoge.txt
/test_find/alex.txt
/opt/all.txt
/opt/_book/123.txt
/opt/Python-3.7.3/pybuilddir.txt
/opt/alltxt.txt
/opt/s15oldboy/qiong.txt
/opt/IIS/keystorePass.txt

()小括号

将一个或多个字符捆绑在一起,当作一个整体进行处理;

  • 小括号功能之一是分组过滤被括起来的内容括号内的内容表示一个整体

  • 括号()内的内容可以被后面的"\n"正则引用n为数字,表示引用第几个括号的内容

    • \1:表示从左侧起,第一个括号中的模式所匹配到的字符
    • \2:从左侧期,第二个括号中的模式所匹配到的字符

1.找出包含good和glad的行

[root@pylinux data]# grep -E 'goo|lad' luffycity.txt        #结果不是我们想要的
good
goooood
goooooood
glad

[root@pylinux data]# grep -E 'good|glad' luffycity.txt    #我们希望能够实现这这样的匹配
good
glad

[root@pylinux data]# grep -E 'g(oo|la)d' luffycity.txt
good
glad

img

分组之后向引用

[root@chaogelinux data]# cat lovers.txt
I like my lover.
I love my lover.
He likes his lovers.
He love his lovers.

[root@chaogelinux data]# grep -E  '(l..e).*\1' lovers.txt
I love my lover.
He love his lovers.

[root@chaogelinux data]# grep -E '(r..t).*\1' /etc/passwd    #案例2
root:x:0:0:root:/root:/bin/bash

最清晰的分组解释

img

{n,m}匹配次数

重复前一个字符各种次数,可以通过-o参数显示明确的匹配过程

img

img

四、sed

sed是Stream Editor(字符流编辑器)的缩写,简称流编辑器。

sed是操作、过滤和转换文本内容的强大工具。

常用功能包括结合正则表达式对文件实现快速增删改查,其中查询的功能中最常用的两大功能是过滤(过滤指定字符串)、取行(取出指定行)。

img

语法:

sed [选项] [sed内置命令字符] [输入文件]

选项:

参数选项 解释
-n 取消默认sed的输出,常与sed内置命令p一起用
-i 直接将修改结果写入文件。不用-i,sed修改的是内存数据
-e 多次编辑,不需要管道符了
-r 支持正则扩展

sed的内置命令字符用于对文件进行不同的操作功能,如对文件增删改查

sed常用内置命令字符

sed的内置命令字符 解释
a append,对文本追加,在指定行后面添加一行/多行文本
d Delete,删除匹配行
i insert,表示插入文本,在指定行前添加一行/多行文本
p Print ,打印匹配行的内容,通常p与-n一起用
s/正则/替换内容/g 匹配正则内容,然后替换内容(支持正则),结尾g代表全局匹配

sed匹配范围

范围 解释
空地址 全文处理
单地址 指定文件某一行
/pattern/ 被模式匹配到的每一行
范围区间 10,20 十到二十行10,+5第10行向下5行/pattern1/,/pattern2/
步长 1~2,表示1、3、5、7、9行2~2两个步长,表示2、4、6、8、10、偶数行

4.1 sed案例

准备测试数据

[root@pylinux data]# cat -n luffycity.txt
     1    My name is chaoge.
     2    I teach linux.
     3    I like play computer game.
     4    My qq is 877348180.
     5    My website is http://pythonav.cn.

1. 输出文件第2,3行的内容

[root@pylinux data]# sed -n '2,3p' luffycity.txt    
I teach linux.
I like play computer game.

img


2. 过滤出含有linux的字符串行

#sed可以实现grep的过滤效果,必须把要过滤的内容放在双斜杠中
[root@pylinux data]# sed -n '/linux/p' luffycity.txt        
I teach linux.

3. 删除含有game的行

注意sed想要修改文件内容,还得用-i参数

[root@pylinux data]# sed '/game/d' luffycity.txt
My name is chaoge.
I teach linux.
My qq is 877348180.
My website is http://pythonav.cn.

img

想要将修改结果写入到文件,还得这么敲

[root@pylinux data]# sed  -i '/game/d' luffycity.txt  #不会输出结果,直接写入文件

删掉2,3两行

[root@pylinux data]# sed '2,3d' luffycity.txt

删除第5行到结尾

[root@pylinux data]# sed '5,$d'  luffycity.txt
My name is chaoge.
----------
I teach linux.
----------

4.将文件中的My全部替换为His

  • s内置符配合g,代表全局替换,中间的"/"可以替换为"#@/"等
[root@pylinux data]# sed 's/My/His/g' luffycity.txt
His name is chaoge.
I teach linux.
I like play computer game.
His qq is 877348180.
His website is http://pythonav.cn.

5.替换所有My为His,同时换掉QQ号为8888888

[root@pylinux data]# sed -e 's/My/His/g' -e 's/877348180/88888/g' luffycity.txt
His name is chaoge.
I teach linux.
I like play computer game.
His qq is 88888.
His website is http://pythonav.cn.

6.在文件第二行追加内容 a字符功能,写入到文件,还得添加 -i

[root@pylinux data]# sed -i '2a I am useing  sed command' luffycity.txt
My name is chaoge.
I teach linux.
I am useing  sed command
I like play computer game.
My qq is 877348180.
My website is http://pythonav.cn.

img

添加多行信息,用换行符"\n"

[root@pylinux data]# sed -i "3a i like linux very much.\nand you?" luffycity.txt
[root@pylinux data]#
[root@pylinux data]# cat -n luffycity.txt
     1    My name is chaoge.
     2    I teach linux.
     3    I am useing  sed command
     4    i like linux very much.
     5    and you?
     6    I like play computer game.
     7    My qq is 877348180.
     8    My website is http://pythonav.cn.

img

在每一行下面插入新内容

[root@pylinux data]# sed "a ----------" luffycity.txt
My name is chaoge.
----------
I teach linux.
----------
I am useing  sed command
----------
i like linux very much.
----------
and you?
----------
I like play computer game.
----------
My qq is 877348180.
----------
My website is http://pythonav.cn.
----------

7.在第二行上面插入内容

[root@pylinux data]# sed '2i i am 27' luffycity.txt
My name is chaoge.
i am 27
----------
I teach linux.
----------
I am useing  sed command
----------
i like linux very much.
----------
and you?
----------
I like play computer game.
----------
My qq is 877348180.
----------
My website is http://pythonav.cn.
----------

4.2 sed配合正则表达式企业案例

上一节是用grep -E 扩展正则表达式,这一节是用sed配合正则表达式使用

取出linux的IP地址

1.删除网卡信息

img

去头去尾法

交给管道符,一次去头,一次去尾

思路:
1.首先取出第二行
[root@pylinux ~]# ifconfig | sed -n '2p'
        inet 10.141.32.137  netmask 255.255.192.0  broadcast 10.141.63.255

2.找到第二行后,去掉ip之前的内容 
[root@pylinux ~]# ifconfig eth0|sed -n '2s/^.*inet//gp'
 10.141.32.137  netmask 255.255.192.0  broadcast 10.141.63.255
 解释: 
 -n是取消默认输出  
 2s是处理第二行内容
 /^.*inet//  是匹配inet前所有的内容
 gp代表全局替换且打印替换结果

3.再次处理,去掉ip后面的内容
[root@pylinux tmp]# ifconfig eth0| sed -n '2s/^.*inet//gp' ip.txt | sed -n 's/net.*$//gp'
 10.141.32.137

 解释:
 net.*$  匹配net到结尾的内容
 s/net.*$//gp   #把匹配到的内容替换为空

-e参数多次编辑

[root@pylinux tmp]# ifconfig eth0  | sed -ne '2s/^.*inet//g'  -e '2s/net.*$//gp'
 10.141.32.137

img

五、awk

awk是一个强大的linux命令,有强大的文本格式化的能力,好比将一些文本数据格式化成专业的excel表的样式

awk早期在Unix上实现,我们用的awk是gawk,是GUN awk的意思

img

awk更是是一门编程语言,支持条件判断、数组、循环等功能

再谈三剑客

  • grep,擅长单纯的查找或匹配文本内容
  • sed,更适合编辑、处理匹配到的文本内容
  • awk,更适合格式化文本内容,对文本进行复杂处理

三个命令称之为Linux的三剑客

5.1 awk基础

awk语法

awk [option] 'pattern[action]'  file ...
awk 参数   '条件动作'  文件

img

  • Action指的是动作,awk擅长文本格式化,且输出格式化后的结果,因此最常用的动作就是printprintf

awk场景

动作场景

img

[root@pylinux tmp]# cat alex.txt
alex1 alex2 alex3 alex4 alex5
alex6 alex7 alex8 alex9 alex10
alex11 alex12 alex13 alex14 alex15
alex16 alex17 alex18 alex19 alex20
alex21 alex22 alex23 alex24 alex25
alex26 alex27 alex28 alex29 alex30
alex31 alex32 alex33 alex34 alex35
alex36 alex37 alex38 alex39 alex40
alex41 alex42 alex43 alex44 alex45
alex46 alex47 alex48 alex49 alex50
[root@pylinux tmp]#
[root@pylinux tmp]#
[root@pylinux tmp]#
[root@pylinux tmp]#
[root@pylinux tmp]# cat alex.txt |awk '{print $2}'
alex2
alex7
alex12
alex17
alex22
alex27
alex32
alex37
alex42
alex47

我们执行的命令是awk '{print $2}',没有使用参数和模式,$2表示输出文本的第二列信息

awk默认以空格为分隔符,且多个空格也识别为一个空格,作为分隔符

awk是按行处理文件,一行处理完毕,处理下一行,根据用户指定的分割符去工作,没有指定则默认空格

指定了分隔符后,awk把每一行切割后的数据对应到内置变量

img

  • $0表示整行
  • $NF表示当前分割后的最后一列
  • 倒数第二列可以写成$(NF-1)

awk内置变量

内置变量 解释
$n 指定分隔符后,当前记录的第n个字段
$0 完整的输入记录
FS 字段分隔符,默认是空格
NF(Number of fields) 分割后,当前行一共有多少个字段
NR(Number of records) 当前记录数,行数
更多内置变量可以man手册查看 man awk

一次性输出多列

[root@pylinux tmp]# awk '{print $1,$2}' alex.txt
alex1 alex2
alex6 alex7
alex11 alex12
alex16 alex17
alex21 alex22
alex26 alex27
alex31 alex32
alex36 alex37
alex41 alex42
alex46 alex47

img

自动定义输出内容

awk,必须外层单引号内层双引号

内置变量$1、$2都不得添加双引号,否则会识别为文本,尽量别加引号

img

[root@pylinux tmp]# awk '{print "第一列",$1,"第二列",$2,"第三列",$3}' alex.txt
第一列 alex1 第二列 alex2 第三列 alex3
第一列 alex6 第二列 alex7 第三列 alex8
第一列 alex11 第二列 alex12 第三列 alex13
第一列 alex16 第二列 alex17 第三列 alex18
第一列 alex21 第二列 alex22 第三列 alex23
第一列 alex26 第二列 alex27 第三列 alex28
第一列 alex31 第二列 alex32 第三列 alex33
第一列 alex36 第二列 alex37 第三列 alex38
第一列 alex41 第二列 alex42 第三列 alex43
第一列 alex46 第二列 alex47 第三列 alex48

输出整行信息

[root@pylinux tmp]# awk '{print}' alex.txt        #两种写法都可以
[root@pylinux tmp]# awk '{print $0}' alex.txt

awk参数

参数 解释
-F 指定分割字段符
-v 定义或修改一个awk内部的变量
-f 从脚本文件中读取awk命令

5.2 awk案例

测试文件内容

[root@pylinux tmp]# cat pwd.txt  -n
     1    sync:x:5:0:sync:/sbin:/bin/sync
     2    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     3    halt:x:7:0:halt:/sbin:/sbin/halt
     4    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
     5    operator:x:11:0:operator:/root:/sbin/nologin
     6    games:x:12:100:games:/usr/games:/sbin/nologin
     7    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
     8    nobody:x:99:99:Nobody:/:/sbin/nologin
     9    systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    10    dbus:x:81:81:System message bus:/:/sbin/nologin
    11    polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    12    libstoragemgmt:x:998:997:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
    13    rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
    14    ntp:x:38:38::/etc/ntp:/sbin/nologin

显示文件第五行

#NR在awk中表示行号,NR==5表示行号是5的那一行
#注意一个等于号,是修改变量值的意思,两个等于号是关系运算符,是"等于"的意思
[root@pylinux tmp]# awk 'NR==5' pwd.txt
operator:x:11:0:operator:/root:/sbin/nologin

显示文件2-5行

设置模式(条件)

#告诉awk,我要看行号2到5的内容
[root@pylinux tmp]# awk 'NR==2,NR==5' pwd.txt
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

给每一行的内容添加行号

添加变量,NR等于行号,$0表示一整行的内容

{print }是awk的动作

[root@pylinux tmp]# awk  '{print NR,$0}'  alex.txt
1 alex1 alex2 alex3 alex4 alex5
2 alex6 alex7 alex8 alex9 alex10
3 alex11 alex12 alex13 alex14 alex15
4 alex16 alex17 alex18 alex19 alex20
5 alex21 alex22 alex23 alex24 alex25
6 alex26 alex27 alex28 alex29 alex30
7 alex31 alex32 alex33 alex34 alex35
8 alex36 alex37 alex38 alex39 alex40
9 alex41 alex42 alex43 alex44 alex45
10 alex46 alex47 alex48 alex49 alex50  alex51

显示文件3-5行且输出行号

[root@pylinux tmp]# awk 'NR==3,NR==5  {print NR,$0}' alex.txt
3 alex11 alex12 alex13 alex14 alex15
4 alex16 alex17 alex18 alex19 alex20
5 alex21 alex22 alex23 alex24 alex25

显示pwd.txt文件的第一列,倒数第二和最后一列

按照:分割

[root@pylinux tmp]# awk -F ':' '{print $1,$(NF-1),$NF}' pwd.txt
sync /sbin /bin/sync
shutdown /sbin /sbin/shutdown
halt /sbin /sbin/halt
mail /var/spool/mail /sbin/nologin
operator /root /sbin/nologin
games /usr/games /sbin/nologin
ftp /var/ftp /sbin/nologin
nobody / /sbin/nologin
systemd-network / /sbin/nologin
dbus / /sbin/nologin
polkitd / /sbin/nologin
libstoragemgmt /var/run/lsm /sbin/nologin
rpc /var/lib/rpcbind /sbin/nologin
ntp /etc/ntp /sbin/nologin

img

5.3 awk分隔符

img

awk的分隔符有两种

  • 输入分隔符,awk默认是空格,空白字符,英文是field separator,变量名是FS
  • 输出分隔符,output field separator,简称OFS

FS输入分隔符

awk逐行处理文本的时候,以输入分割符为准,把文本切成多个片段,默认符号是空格

当我们处理特殊文件,没有空格的时候,可以自由指定分隔符特点

[root@pylinux tmp]# awk -F '#' '{print $1}' chaoge.txt
超哥c
超哥f
超哥i
超哥l
超哥o
超哥r
超哥u
超哥x

img

  • 除了使用-F选项,还可以使用变量的形式,指定分隔符,使用-v选项搭配,修改FS变量
[root@pylinux tmp]# awk -v FS='#' '{print $1}' chaoge.txt
超哥c
超哥f
超哥i
超哥l
超哥o
超哥r
超哥u
超哥x

OFS输出分割符

awk执行完命令,默认用空格隔开每一列,这个空格就是awk的默认输出符,例如

[root@pylinux tmp]# cat chaoge.txt
超哥c#超哥d#超哥e
超哥f#超哥g#超哥h
超哥i#超哥j#超哥k
超哥l#超哥m#超哥n
超哥o#超哥p#超哥q
超哥r#超哥s#超哥t
超哥u#超哥v#超哥w
超哥x#超哥y#超哥z
[root@pylinux tmp]# awk -v FS='#' '{print $1,$3}' chaoge.txt
超哥c 超哥e
超哥f 超哥h
超哥i 超哥k
超哥l 超哥n
超哥o 超哥q
超哥r 超哥t
超哥u 超哥w
超哥x 超哥z

img

通过OFS设置输出分割符,记住修改变量必须搭配选项 -v

[root@pylinux tmp]# cat chaoge.txt
超哥c#超哥d#超哥e
超哥f#超哥g#超哥h
超哥i#超哥j#超哥k
超哥l#超哥m#超哥n
超哥o#超哥p#超哥q
超哥r#超哥s#超哥t
超哥u#超哥v#超哥w
超哥x#超哥y#超哥z
[root@pylinux tmp]#
[root@pylinux tmp]#
[root@pylinux tmp]# awk -v FS='#' -v OFS='---' '{print $1,$3 }' chaoge.txt
超哥c---超哥e
超哥f---超哥h
超哥i---超哥k
超哥l---超哥n
超哥o---超哥q
超哥r---超哥t
超哥u---超哥w
超哥x---超哥z
[root@pylinux tmp]#

img

输出分隔符与逗号

awk是否存在输出分隔符,特点在于'{print $1,$3 } 逗号的区别

  • 添加逗号,默认是空格分隔符
[root@pylinux tmp]# awk -v FS='#'  '{print $1,$3 }' chaoge.txt
超哥c 超哥e
超哥f 超哥h
超哥i 超哥k
超哥l 超哥n
超哥o 超哥q
超哥r 超哥t
超哥u 超哥w
超哥x 超哥z
  • 不加逗号
[root@pylinux tmp]# awk -v FS='#'  '{print $1$3 }' chaoge.txt
超哥c超哥e
超哥f超哥h
超哥i超哥k
超哥l超哥n
超哥o超哥q
超哥r超哥t
超哥u超哥w
超哥x超哥z
  • 修改分割符,改为\t(制表符,四个空格)或者任意字符
[root@pylinux tmp]# awk -v FS='#' -v OFS='\t\t' '{print $1,$3 }' chaoge.txt
超哥c        超哥e
超哥f        超哥h
超哥i        超哥k
超哥l        超哥n
超哥o        超哥q
超哥r        超哥t
超哥u        超哥w
超哥x        超哥z

5.4 awk变量

awk参数

参数 解释
-F 指定分割字段符
-v 定义或修改一个awk内部的变量
-f 从脚本文件中读取awk命令

对于awk而言,变量分为

  • 内置变量
  • 自定义变量
内置变量 解释
FS 输入字段分隔符, 默认为空白字符
OFS 输出字段分隔符, 默认为空白字符
RS 输入记录分隔符(输入换行符), 指定输入时的换行符
ORS 输出记录分隔符(输出换行符),输出时用指定符号代替换行符
NF NF:number of Field,当前行的字段的个数(即当前行被分割成了几列),字段数量
NR NR:行号,当前处理的文本行的行号。
FNR FNR:各文件分别计数的行号
FILENAME FILENAME:当前文件名
ARGC ARGC:命令行参数的个数
ARGV ARGV:数组,保存的是命令行所给定的各参数

内置变量

NR,NF、FNR

  • awk的内置变量NR、NF是不用添加$符号的
  • $0 $1 $2 $3 ... 是需要添加$符号的

输出每行行号,以及字段总个数

[root@pylinux tmp]# cat -n alex.txt
     1    alex1 alex2 alex3 alex4 alex5
     2    alex6 alex7 alex8 alex9 alex10
     3    alex11 alex12 alex13 alex14 alex15
     4    alex16 alex17 alex18 alex19 alex20
     5    alex21 alex22 alex23 alex24 alex25
     6    alex26 alex27 alex28 alex29 alex30
     7    alex31 alex32 alex33 alex34 alex35
     8    alex36 alex37 alex38 alex39 alex40
     9    alex41 alex42 alex43 alex44 alex45
    10    alex46 alex47 alex48 alex49 alex50  alex51
[root@pylinux tmp]#
[root@pylinux tmp]# awk '{print NR,NF}' alex.txt
1 5
2 5
3 5
4 5
5 5
6 5
7 5
8 5
9 5
10 6

输出每行行号,以及指定的列

[root@pylinux tmp]# awk '{print NR,$1,$5}' alex.txt
1 alex1 alex5
2 alex6 alex10
3 alex11 alex15
4 alex16 alex20
5 alex21 alex25
6 alex26 alex30
7 alex31 alex35
8 alex36 alex40
9 alex41 alex45
10 alex46 alex50

处理多个文件显示行号

#  普通的NR变量,会将多个文件按照顺序排序
[root@pylinux tmp]# awk '{print NR,$0}' alex.txt  pwd.txt
#使用FNR变量,可以分别对文件行数计数
[root@pylinux tmp]# awk '{print FNR,$0}' alex.txt  pwd.txt

内置变量RS

RS变量作用是输入分隔符,默认是回车符,也就是回车(Enter键)换行符

我们也可以自定义空格作为行分隔符,每遇见一个空格,就换行处理

img

[root@pylinux tmp]# awk -v RS=' ' '{print NR,$0}' chaoge.txt

内置变量ORS

ORS是输出分隔符的意思,awk默认认为,每一行结束了,就得添加回车换行符

ORS变量可以更改输出符

awk -v ORS='@@@' '{print NR,$0}' chaoge.txt

img

内置变量FILENAME

显示awk正在处理文件的名字

[root@pylinux tmp]# awk '{print FILENAME,FNR,$0}' chaoge.txt   alex.txt
chaoge.txt 1 超哥a 超哥b
chaoge.txt 2 超哥c 超哥d 超哥e
chaoge.txt 3 超哥f 超哥g 超哥h
chaoge.txt 4 超哥i 超哥j 超哥k
chaoge.txt 5 超哥l 超哥m 超哥n
chaoge.txt 6 超哥o 超哥p 超哥q
chaoge.txt 7 超哥r 超哥s 超哥t
chaoge.txt 8 超哥u 超哥v 超哥w
chaoge.txt 9 超哥x 超哥y 超哥z
alex.txt 1 alex1 alex2 alex3 alex4 alex5
alex.txt 2 alex6 alex7 alex8 alex9 alex10
alex.txt 3 alex11 alex12 alex13 alex14 alex15
alex.txt 4 alex16 alex17 alex18 alex19 alex20

变量ARGC、ARGV

ARGV表示的是一个数组,数组中保存的是命令行所给的参数

数组是一种数据类型,如同一个盒子

盒子有它的名字,且内部有N个小格子,标号从0开始

给一个盒子起名字叫做months,月份是1~12,那就如图所示

img

img

[root@pylinux tmp]# awk 'BEGIN{print "超哥教你学内置awk变量呢"}'  chaoge.txt
超哥教你学内置awk变量呢
[root@pylinux tmp]#
[root@pylinux tmp]# awk 'BEGIN{print "超哥教你学内置awk变量呢",ARGV[0]}'  chaoge.txt
超哥教你学内置awk变量呢 awk
[root@pylinux tmp]#
[root@pylinux tmp]# awk 'BEGIN{print "超哥教你学内置awk变量呢",ARGV[0],ARGV[1]}'  chaoge.txt
超哥教你学内置awk变量呢 awk chaoge.txt
[root@pylinux tmp]#
[root@pylinux tmp]# awk 'BEGIN{print "超哥教你学内置awk变量呢",ARGV[0],ARGV[1],ARGV[2]}'  chaoge.txt   alex.txt
超哥教你学内置awk变量呢 awk chaoge.txt alex.txt

自定义变量

顾名思义,是我们自己定义变量

  • 方法一,-v varName=value
  • 方法二,在程序中直接定义

方法一:

[root@pylinux tmp]# awk -v luffyVarName="超哥nb,awk讲的好啊"  'BEGIN{print luffyVarName}' chaoge.txt
超哥nb,awk讲的好啊

img

方法二:

[root@pylinux tmp]# awk 'BEGIN{chaogeVar="超哥带你学linux,还怕学不会咋的";chaogeVar2="学的会,必须学得会" ;print chaogeVar,chaogeVar2}'
超哥带你学linux,还怕学不会咋的 学的会,必须学得会

img

方法三:间接引用shell变量

[root@pylinux tmp]# studyLinux="超哥讲的linux是真滴好,嘿嘿"
[root@pylinux tmp]#
[root@pylinux tmp]#
[root@pylinux tmp]# awk -v myVar=$studyLinux 'BEGIN{print myVar}'    # -v是给awk定义变量
超哥讲的linux是真滴好,嘿嘿

5.5 awk格式化

前面我们接触到的awk的输出功能,是{print}的功能,只能对文本简单的输出,并不能美化或者修改格式

printf格式化输出

如果你学过C语言或是go语言,一定见识过printf()函数,能够对文本格式化输出

printf和print的区别

format的使用

要点:
1、其与print命令的最大不同是,printf需要指定format;
2、format用于指定后面的每个item的输出格式;
3、printf语句不会自动打印换行符;\n

format格式的指示符都以%开头,后跟一个字符;如下:
%c: 显示字符的ASCII码;
%d, %i:十进制整数;
%e, %E:科学计数法显示数值;
%f: 显示浮点数;
%g, %G: 以科学计数法的格式或浮点数的格式显示数值;
%s: 显示字符串;
%u: 无符号整数;
%%: 显示%自身;

printf修饰符:
-: 左对齐;默认右对齐,
+:显示数值符号; printf "%+d"

  • printf动作默认不会添加换行符
  • print默认添加空格换行符
[root@pylinux tmp]# awk '{print $1}' 超哥nb.txt
超哥nb1
超哥nb4
超哥nb7
超哥nb10
[root@pylinux tmp]# awk '{printf $1}' 超哥nb.txt
超哥nb1超哥nb4超哥nb7超哥nb10

给printf添加格式

  • 格式化字符串 %s 代表字符串的意思
[root@pylinux tmp]# awk '{printf "%s\n",$1}' 超哥nb.txt
超哥nb1
超哥nb4
超哥nb7
超哥nb10

img

对多个变量进行格式化

当我们使用linux命令printf时,是这样的,一个%s格式替换符,可以对多个参数进行重复格式化

[root@pylinux tmp]# printf  "%s\n"  a b c d
a
b
c
d

然而awk的格式替换符想要修改多个变量,必须传入多个

[root@pylinux tmp]# awk 'BEGIN{printf "%d\n%d\n%d\n%d\n%d\n",1,2,3,4,5}'
1
2
3
4
5

img

  • printf对输出的文本不会换行,必须添加对应的格式替换符\n
  • 使用printf动作,'{printf "%s\n",$1}',替换的格式和变量之间得有逗号,
  • 使用printf动作,%s %d 等格式化替换符 必须 和被格式化的数据一一对应

printf案例

[root@pylinux tmp]# cat  超哥nb.txt
超哥nb1 超哥nb2 超哥nb3
超哥nb4 超哥nb5 超哥nb6
超哥nb7 超哥nb8 超哥nb9
超哥nb10

[root@pylinux tmp]# awk '{printf "第一列:%s  第二列:%s  第三列:%s\n",$1,$2,$3}' 超哥nb.txt
第一列:超哥nb1  第二列:超哥nb2  第三列:超哥nb3
第一列:超哥nb4  第二列:超哥nb5  第三列:超哥nb6
第一列:超哥nb7  第二列:超哥nb8  第三列:超哥nb9
第一列:超哥nb10  第二列:  第三列:

img

  • awk通过空格切割文档
  • printf动作对数据格式化

对pwd.txt文件格式化

img

awk -F ":" 'BEGIN{printf "%-25s\t %-25s\t %-25s\t %-25s\t %-25s\t %-25s\t %-25s\n","用户名","密码","UID","GID","用户注释","用户家目录","用户使用的解释器"} {printf "%-25s\t %-25s\t %-25s\t %-25s\t %-25s\t %-25s\t %s\n",$1,$2,$3,$4,$5,$6,$7}' pwd.txt

参数解释
'BEGIN{printf "格式替换符 格式替换符2","变量1","变量2"}'  执行BEGIN模式

%s是格式替换符 ,替换字符串
%s\t 格式化字符串后,添加制表符,四个空格
%-25s  已然是格式化字符串, - 代表左对齐  ,25个字符长度

5.6 awk模式pattern

再来回顾下awk的语法

awk [option] 'pattern[action]'  file ...

awk是按行处理文本,刚才讲解了print动作,现在讲解特殊的patternBEGINEND

  • BEGIN模式是处理文本之前需要执行的操作
  • END模式是处理完所有行之后执行的操作
[root@pylinux tmp]# awk 'BEGIN{print "超哥教你学awk"}'
超哥教你学awk

#上述操作没有指定任何文件作为数据源,而是awk首选会执行BEGIN模式指定的print操作,打印出如上结果,然后发现没有任何文件需要操作,就结束了

img

  • 再次总结,BEGIN就是处理文本前,先执行BEGIN模式指定的动作
  • 再来看END的作用(awk处理完所有指定的文本后,需要执行的动作)

img

awk结合BEGIN和END模式

[root@pylinux tmp]# awk 'BEGIN{print "来路飞学城听超哥讲linux"}{print $1,$2}END{print "超哥nb"}' alex.txt

img

awk模式pattern讲解

再来看一下awk的语法,模式也可以理解为是条件

awk [option] 'pattern[action]'  file ...

刚才我们学了两个模式(条件)

  • BEGIN
  • END

awk默认是按行处理文本,如果不指定任何模式(条件),awk默认一行行处理

如果指定了模式,只有符合模式的才会被处理

模式(条件)案例

img

awk的模式

关系运算符 解释 示例
< 小于 x<y
<= 小于等于 x<=y
== 等于 x==y
!= 不等于 x!=y
>= 大于等于 x>=y
> 大于 x>y
~ 匹配正则 x~/正则/
!~ 不匹配正则 x!~/正则/

案例

img

awk基础总结

  • 空模式,没有指定任何的模式(条件),因此每一行都执行了对应的动作,空模式会匹配文档的每一行,每一行都满足了(空模式)
[root@pylinux tmp]# awk '{print $1}' alex.txt
alex1
alex6
alex11
alex16
alex21
alex26
alex31
alex36
alex41
alex46
  • 关系运算符模式,awk默认执行打印输出动作
[root@pylinux tmp]# awk 'NR==2,NR==5' alex.txt
alex6 alex7 alex8 alex9 alex10
alex11 alex12 alex13 alex14 alex15
alex16 alex17 alex18 alex19 alex20
alex21 alex22 alex23 alex24 alex25
  • BEGIN/END模式(条件设置)

img

awk与正则表达式

正则表达式主要与awk的pattern模式(条件)结合使用

  • 不指定模式,awk每一行都会执行对应的动作
  • 指定了模式,只有被模式匹配到的、符合条件的行才会执行动作

找出pwd.txt中有以games开头的行

1.用grep过滤

[root@pylinux tmp]# cat -n pwd.txt
     1    sync:x:5:0:sync:/sbin:/bin/sync
     2    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     3    halt:x:7:0:halt:/sbin:/sbin/halt
     4    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
     5    operator:x:11:0:operator:/root:/sbin/nologin
     6    games:x:12:100:games:/usr/games:/sbin/nologin
     7    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
     8    nobody:x:99:99:Nobody:/:/sbin/nologin
     9    systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    10    dbus:x:81:81:System message bus:/:/sbin/nologin
    11    polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    12    libstoragemgmt:x:998:997:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
    13    rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
    14    ntp:x:38:38::/etc/ntp:/sbin/nologin

[root@pylinux tmp]# grep '^games' pwd.txt
games:x:12:100:games:/usr/games:/sbin/nologin

2.awk怎么办?

[root@pylinux tmp]# awk '/^games/{print $0}'  pwd.txt
games:x:12:100:games:/usr/games:/sbin/nologin

#省略写法
[root@pylinux tmp]# awk '/^games/'  pwd.txt
games:x:12:100:games:/usr/games:/sbin/nologin

awk使用正则语法

img

awk命令使用正则表达式,必须把正则放入 "//" 双斜杠中,匹配到结果后执行动作{print $0},打印整行信息

grep可以过滤,那我还用你awk干啥?

awk强大的格式化文本

img

[root@pylinux tmp]# awk -F ":"  'BEGIN{printf "%-10s\t%-10s\n","用户名","用户id"} /^n/ {printf "%-10s\t%-10s\n",$1,$3}' pwd.txt
用户名           用户id
nobody        99
ntp           38
nawerwertp    38
nqwerqstp     38
nqweqsdtp     38
nqwetp        38

awk命令执行流程

解读需求:从pwd.txt文件中,寻找我们想要的信息,按照以下顺序执行

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
  1. 优先执行BEGIN{}模式中的语句
  2. 从pwd.txt文件中读取第一行,然后执行pattern{commands}进行正则匹配/^n/ 寻找n开头的行,找到了执行{print} 进行打印
  3. 当awk读取到文件数据流的结尾时,会执行END{commands}

找出pwd.txt文件中禁止登录的用户(/sbin/nologin

正则表达式中如果出现了 "/"则需要进行转义

找出pwd.txt文件中禁止登录的用户(/sbin/nologin

1.用grep找出

grep '/sbin/nologin$' pwd.txt

img

2.awk用正则得用双斜杠/正则表达式/

[root@pylinux tmp]# awk '/\/sbin\/nologin$/{print $0}' pwd.txt

img

找出文件的区间内容

1.找出mail用户到nobody用户之间的内容

img

[root@pylinux tmp]# awk '/^mail/,/^nobody/ {print $0}' pwd.txt
mail:x:8:12:mail:/var/spool/mail:/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
nobody:x:99:99:Nobody:/:/sbin/nologin

2.关系表达式模式

[root@pylinux tmp]# awk 'NR>=4 && NR<=8 {print $0}' pwd.txt
mail:x:8:12:mail:/var/spool/mail:/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
nobody:x:99:99:Nobody:/:/sbin/nologin

awk企业实战nginx日志

Access.log

39.96.187.239 - - [11/Nov/2019:10:08:01 +0800] "GET / HTTP/1.1" 302 0 "-" "Zabbix"
211.162.238.91 - - [11/Nov/2019:10:08:02 +0800] "GET /api/v1/course_sub/category/list/?belong=1 HTTP/1.1" 200 363 "https://www.luffycity.com/free" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
211.162.238.91 - - [11/Nov/2019:10:08:02 +0800] "GET /api/v1/degree_course/ HTTP/1.1" 200 370 "https://www.luffycity.com/free" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"

统计日志的访客ip数量

#sort -n 数字从大到小排序
#wc -l 统计行数,也就是ip的条目数
[root@pylinux tmp]# awk '{print $1}' 500access.log |sort -n|uniq|wc -l
75

查看访问最频繁的前10个ip

#uniq -c 去重显示次数
#sort -n 从大到小排序

1.先找出所有ip排序,排序,然后去重统计出现次数
awk '{print $1}' 500access.log |sort -n |uniq -c

2.再次从大到小排序,且显示前100个ip
[root@pylinux tmp]# awk '{print $1}' 500access.log |sort -n |uniq -c |sort -nr |head -10
     32 113.225.0.211
     22 119.123.30.32
     21 116.30.195.155
     20 122.71.65.73
     18 163.142.211.160
     16 39.96.187.239
     16 124.200.147.165
     16 101.249.53.64
     14 120.228.193.218
     14 113.68.155.221

img

posted @ 2023-05-30 17:19  王陸  阅读(90)  评论(0编辑  收藏  举报