Shell正则表达式与文本处理三剑客grep、sed、awk示例详解

Written by

in

文章目录
  • Shell正则表达式分为两种: 基础正则表达式:BRE(basic regular express) 扩展正则表达式:ERE(extend regular express),扩展的表达式有+、?、|和()
  • 过滤来自一个文件或标准输入匹配模式内容。 除此之外还有: grep -f:从文件每一行获取匹配模式 grep -m:输出匹配的结果num数 grep -H:打印每个匹配的文件名 grep -h:不输出文件名 grep -q:不输出正常信息 grep -s:不输出错误信息 grep -r:递归目录 grep -B:打印匹配的前几行 grep -A:打印匹配的后几行 grep -C:打印匹配的前后几行 grep –color:匹配的字体颜色 (1)输出b文件在a文件相同的行 > grep -f a b (2)输出b文件在a文件不同的行 > grep -v -f a b (3)匹配多个模式 > echo “a bc de” |xargs -n1 |grep -e ‘a’ -e ‘bc’ a bc 注:xargs为多行输出,-n1表示一行输出1个参数 (4)去除文件内的空行和#开头的行(一般用于查看配置文件) > grep -E -v “^$|.*#” /etc/httpd/conf/httpd.conf (5)匹配开头不分大小写的单词 > echo “A a b c” |xargs -n1 |grep -i a A a (6)只显示匹配的字符串 > echo “this is a test” |grep -o ‘is’ is is (7)输出匹配的前五个结果 > seq 1 20 |grep -m 5 -E ‘[0-9]{2}’ 10 11 12 13 14  (8)统计匹配多少行 > seq 1 20 |grep -c -E ‘[0-9]{2}’ 11 (9)匹配b字符开头的行 > echo “a bc de” |xargs -n1 |grep ‘^b’ bc (10)匹配de字符结尾的行并输出匹配的行 > echo “a ab abc abcd abcde” |xargs -n1 |grep -n ‘de$’ 5:abcde (11)递归搜索/etc目录下包含ip的conf后缀文件 grep –include:只检索匹配的文件 > grep -r ‘192.167.1.1’ /etc –include *.conf (12)排除搜索bak后缀的文件 grep –exclude:跳过匹配的文件 > grep -r ‘192.167.1.1’ /opt –exclude *.bak (13)匹配所有IP > ifconfig |grep -E -o “[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}” (14)打印匹配结果及后3行 > seq 1 10 |grep 5 -A 3 5 6 7 8 (15)打印匹配结果及前3行 > seq 1 10 |grep 5 -B 3 2 3 4 (16)打印匹配结果及前后3行 > seq 1 10 |grep 5 -C 3 2 3 4 5 6 7 8
  • 流编辑器,过滤和替换文本。 工作原理:sed命令将当前处理的行读入模式空间进行处理,处理完把结果输出,并清空模式空间。然后再将下一行读入模式空间进行处理输出,以此类推,直到最后一行。还有一个空间叫保持空间,又称暂存空间,可以暂时存放一些处理的数据,但不能直接输出,只能放到模式空间输出。 这两个空间其实就是在内存中初始化的一个内存区域,存放正在处理的数据和临时存放的数据。 语法格式:sed [选项] '地址 命令' file 借助一些文本内容作为示例: [root@openEuler-1 script]# cat sed.txt nimgtw 48003/udp # Nimbus Gateway 3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol isnetserv 48128/tcp # Image Systems Network Services isnetserv 48128/udp # Image Systems Network Services blp5 48129/tcp # Bloomberg locator blp5 48129/udp # Bloomberg locator com-bardac-dw 48556/tcp # com-bardac-dw com-bardac-dw 48556/udp # com-bardac-dw iqobject 48619/tcp # iqobject iqobject 48619/udp # iqobject
  • awk 是一个处理文本的编程语言工具,能用简短的程序处理标准输入或文件、数据排序、计算以及 生成报表等。 基本的命令语法:awk option 'pattern {action}' file 其中pattern表示AWK在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。花括号用于根据特定的模式对一系列指令进行分组。 awk 处理的工作方式与数据库类似,支持对记录和字段处理,这也是grep和sed不能实现的。在awk中,缺省的情况下将文本文件中的一行视为一个记录,逐行放到内存中处理,而将一行中的某一部分作为记录中的一个字段。用1,2,3…数字的方式顺序的表示行(记录)中的不同字段。用$后跟数字,引用对应的字段,以逗号分隔,0表示整个行。
  • 目录
    • 一、正则表达式
      • 1.1 基本正则表达式
      • 1.2 扩展正则表达式
      • 1.3 支持正则表达式的工具
    • 二、grep
      • 三、sed
        • 3.1 匹配打印(p)
        • 3.2 匹配删除(d)
        • 3.3 替换(s///)
        • 3.4 多重编辑(-e)
        • 3.5 添加新内容(a,i、c)
        • 3.6 读取文件并追加到匹配行后(r)
        • 3.7 将匹配行写入文件(w)
        • 3.8 读取下一行(n和N)
        • 3.9 打印和删除模式空间的第一行(P和D)
        • 3.10 保持空间操作(h与H、g与G和x)
        • 3.11 忽略大小写匹配(I)
        • 3.12 获取总行数
      • 四、awk
        • 4.1 选项、模式
        • 4.2 内置变量
        • 4.3 操作符
        • 4.4 流程控制
        • 4.5 内置函数
        • 4.6  I/O语句
        • 4.7 printf语句

      Shell正则表达式分为两种:

      基础正则表达式:BRE(basic regular express)

      扩展正则表达式:ERE(extend regular express),扩展的表达式有+、?、|和()

      grep:默认不支持扩展表达式,加-E选项开启ERE。如果不加-E使用花括号要加转义符{}

      egrep:支持基础和扩展表达式

      awk:支持egrep所有的正则表达式

      sed:默认不支持扩展表达式,加-r选项开启ERE。如果不加-r使用花括号要加转义符{}

      过滤来自一个文件或标准输入匹配模式内容。

      除此之外还有:

      grep -f:从文件每一行获取匹配模式

      grep -m:输出匹配的结果num数

      grep -H:打印每个匹配的文件名

      grep -h:不输出文件名

      grep -q:不输出正常信息

      grep -s:不输出错误信息

      grep -r:递归目录

      grep -B:打印匹配的前几行

      grep -A:打印匹配的后几行

      grep -C:打印匹配的前后几行

      grep –color:匹配的字体颜色

      (1)输出b文件在a文件相同的行

      > grep -f a b

      (2)输出b文件在a文件不同的行

      > grep -v -f a b 

      (3)匹配多个模式

      > echo "a bc de" |xargs -n1 |grep -e 'a' -e 'bc' 
      a 
      bc 

      注:xargs为多行输出,-n1表示一行输出1个参数

      (4)去除文件内的空行和#开头的行(一般用于查看配置文件)

      > grep -E -v "^$|.*#" /etc/httpd/conf/httpd.conf

      (5)匹配开头不分大小写的单词

      > echo "A a b c" |xargs -n1 |grep -i a
      A
      a

      (6)只显示匹配的字符串

      > echo "this is a test" |grep -o 'is' 
      is
      is

      (7)输出匹配的前五个结果

      > seq 1 20 |grep -m 5 -E '[0-9]{2}' 
      10 
      11 
      12 
      13 
      14

       (8)统计匹配多少行

      > seq 1 20 |grep -c -E '[0-9]{2}' 
      11

      (9)匹配b字符开头的行

      > echo "a bc de" |xargs -n1 |grep '^b'
      bc

      (10)匹配de字符结尾的行并输出匹配的行

      > echo "a ab abc abcd abcde" |xargs -n1 |grep -n 'de$' 
      5:abcde 

      (11)递归搜索/etc目录下包含ip的conf后缀文件

      grep –include:只检索匹配的文件

      > grep -r '192.167.1.1' /etc --include *.conf 

      (12)排除搜索bak后缀的文件

      grep –exclude:跳过匹配的文件

      > grep -r '192.167.1.1' /opt --exclude *.bak 

      (13)匹配所有IP

      > ifconfig |grep -E -o "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" 

      (14)打印匹配结果及后3行

      > seq 1 10 |grep 5 -A 3 
      5 
      6 
      7 
      8

      (15)打印匹配结果及前3行

      > seq 1 10 |grep 5 -B 3 
      2 
      3 
      4

      (16)打印匹配结果及前后3行

      > seq 1 10 |grep 5 -C 3 
      2 
      3 
      4 
      5 
      6 
      7 
      8 

      流编辑器,过滤和替换文本。

      工作原理:sed命令将当前处理的行读入模式空间进行处理,处理完把结果输出,并清空模式空间。然后再将下一行读入模式空间进行处理输出,以此类推,直到最后一行。还有一个空间叫保持空间,又称暂存空间,可以暂时存放一些处理的数据,但不能直接输出,只能放到模式空间输出。

      这两个空间其实就是在内存中初始化的一个内存区域,存放正在处理的数据和临时存放的数据。

      语法格式:sed [选项] '地址 命令' file

      借助一些文本内容作为示例:

      [root@openEuler-1 script]# cat sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      
      

      (1)打印匹配blp5开头的行

      [root@openEuler-1 script]# sed -n '/^blp5/p' sed.txt
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      

      (2)打印第一行

      [root@openEuler-1 script]# sed -n '1p' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      

      (3)打印第一行至第三行

      [root@openEuler-1 script]# sed -n '1,3p' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      

      (4)打印奇数行

      [root@openEuler-1 script]# seq 10 | sed -n '1~2p'
      1
      3
      5
      7
      9
      

      (5)打印匹配行及后一行

      [root@openEuler-1 script]# sed -n '/blp5/,+1p' sed.txt
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      

      (6)打印最后一行

      [root@openEuler-1 script]# sed -n '$p' sed.txt
      iqobject          48619/udp            # iqobject
      

      (7)不打印最后一行

      感叹号也就是对后面的命令取反。

      [root@openEuler-1 script]# sed -n '$!p' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      

      (8)匹配范围blp5开头的行~com开头的行

      以逗号分开两个样式选择某个范围。

      [root@openEuler-1 script]# sed -n '/^blp5/,/^com/p' sed.txt
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      

      删除与打印使用方法类似,打印是把匹配的打印出来,删除是把匹配的删除,删除只是不用-n选项。

      (1)删除包含blp5的行

      [root@openEuler-1 script]# sed '/^blp5/d' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (2)删除1~3行

      [root@openEuler-1 script]# sed '1,3d' sed.txt
      isnetserv         48128/udp            # Image Systems Network Services
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject

      (3)去除http.conf文件空行和开头#号的行

      [root@openEuler-1 script]# sed '/^$/d;/.*#/d' /etc/httpd/conf/httpd.conf
      

      (1)替换blp5字符串为test

      [root@openEuler-1 script]# sed 's/blp5/test/' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      test              48129/tcp            # Bloomberg locator
      test              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (2)替换开头是blp5的字符串并打印

      [root@openEuler-1 script]# sed -n 's/blp5/test/p' sed.txt
      test              48129/tcp            # Bloomberg locator
      test              48129/udp            # Bloomberg locator
      

      (3)使用&命令引用匹配内容并替换

      [root@openEuler-1 script]# sed 's/48049/&.0/' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049.0/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (4)给IP加引号

      g:全局替换

      [root@openEuler-1 script]# echo "192.168.121.11 172.1.1.2 223.5.5.5" | sed -r 's/[^ ]+/“&”/g'
      “192.168.121.11” “172.1.1.2” “223.5.5.5”
      

      (5)对1-5行的blp5进行替换

      [root@openEuler-1 script]# sed '1,5s/blp5/test/' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      test              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (6)对匹配行进行替换

      [root@openEuler-1 script]# sed '/48129/tcp/s/blp5/test/' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      test              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (7)二次匹配替换

      [root@openEuler-1 script]# sed 's/blp5/test/;s/3g/4g/' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      4gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      test              48129/tcp            # Bloomberg locator
      test              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (8)注释匹配行后的多少行

      [root@openEuler-1 script]# seq 10 | sed '/5/,+3s/^/#/'
      1
      2
      3
      4
      #5
      #6
      #7
      #8
      9
      10
      

      [root@openEuler-1 script]# sed -e '1,2d' -e 's/blp5/test/' sed.txt
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      test              48129/tcp            # Bloomberg locator
      test              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      
      # 也可以使用;分隔
      [root@openEuler-1 script]# sed '1,2d;s/blp5/test/' sed.txt
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      test              48129/tcp            # Bloomberg locator
      test              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (1)在blp5上一行添加test

      [root@openEuler-1 script]# sed '/blp5/i test' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      test
      blp5              48129/tcp            # Bloomberg locator
      test
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (2)在blp5下一行添加test

      [root@openEuler-1 script]# sed '/blp5/a test' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      blp5              48129/tcp            # Bloomberg locator
      test
      blp5              48129/udp            # Bloomberg locator
      test
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      (3)将blp5替换新行

      [root@openEuler-1 script]# sed '/blp5/c test' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      test
      test
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      [root@openEuler-1 script]# cat a.txt
      123
      456
      [root@openEuler-1 script]# sed '/blp5/r a.txt' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      blp5              48129/tcp            # Bloomberg locator
      123
      456
      blp5              48129/udp            # Bloomberg locator
      123
      456
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      

      [root@openEuler-1 script]# sed '/blp5/w b.txt' sed.txt
      nimgtw            48003/udp            # Nimbus Gateway
      3gpp-cbsp         48049/tcp            # 3GPP Cell Broadcast Service Protocol
      isnetserv         48128/tcp            # Image Systems Network Services
      isnetserv         48128/udp            # Image Systems Network Services
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      com-bardac-dw     48556/tcp            # com-bardac-dw
      com-bardac-dw     48556/udp            # com-bardac-dw
      iqobject          48619/tcp            # iqobject
      iqobject          48619/udp            # iqobject
      [root@openEuler-1 script]# cat b.txt
      blp5              48129/tcp            # Bloomberg locator
      blp5              48129/udp            # Bloomberg locator
      

      n 读取下一行到模式空间。

      N 追加下一行内容到模式空间,并以换行符n分隔。

      (1)打印匹配的下一行

      [root@openEuler-1 script]# seq 5 |sed -n '/3/{n;p}'
      4

      (2)打印偶数

      [root@openEuler-1 script]# seq 10 | sed -n 'n;p'
      2
      4
      6
      8
      10
      # sed先读取第一行1,执行n命令,获取下一行2,此时模式空间是2,
      # 执行p命令,打印模式空间。 现在模式空间是2,sed再读取3,
      # 执行n命令,获取下一行4,此时模式空间为4,执行p命令,以此类推.

      (3)打印奇数

      [root@openEuler-1 script]# seq 10 |sed 'n;d'
      1
      3
      5
      7
      9
      # sed先读取第一行1,此时模式空间是1,并打印模式空间1,
      # 执行n命令,获取下一行2,执行d命令,删除模式空间的2,sed再读取3,
      # 此时模式空间是3,并打印模式空间,再执行n命令,获取下一行4,
      # 执行d命令,删除模式空间的3,以此类推.

      P 打印模式空间的第一行。

      D 删除模式空间的第一行。

      (1)打印奇数

      [root@openEuler-1 script]# seq 6 | sed -n 'N;P'
      1
      3
      5
      

      (2)保留最后一行

      [root@openEuler-1 script]# seq 6 | sed 'N;D'
      6
      # 读取第一行1,执行N命令读取下一行并追加到模式空间,
      # 此时模式空间是1n2,执行D命令删除模式空间第一行1,剩余2.
      # 读取第二行,执行N命令,此时模式空间是3n4,
      # 执行D命令删除模式空间第一行3,剩余4,以此类推.

      h 复制模式空间内容到保持空间(覆盖)。

      H 复制模式空间内容追加到保持空间。

      g 复制保持空间内容到模式空间(覆盖)。

      G 复制保持空间内容追加到模式空间。

      x 模式空间与保持空间内容互换。

      (1)将匹配的内容覆盖到另一个匹配

      [root@openEuler-1 script]# seq 6 | sed -e '/3/{h;d}' -e '/5/g'
      1
      2
      4
      3
      6
      # h命令把匹配的3复制到保持空间,d命令删除模式空间的3.
      # 后面命令再对模式空间匹配5,并用g命令把保持空间3覆盖模式空间5.

      (2)将匹配的内容放到最后

      [root@openEuler-1 script]# seq 6 | sed -e '/3/{h;d}' -e '$G'
      1
      2
      4
      5
      6
      3
      # 这里的$代表最后一行,G表示将保持空间的内容追加到当前行的后面

      (3)交换模式空间和保持空间

      [root@openEuler-1 script]# seq 6 | sed -e '/3/{h;d}' -e '/5/x' -e '$G'
      1
      2
      4
      3
      6
      5
      # 在模式空间匹配5并将保持空间的3与5交换,5就变成了3.
      # 最后把保持空间的5追加到模式空间. 

      (4)倒序输出

      [root@openEuler-1 script]# seq 5 |sed '1!G;h;$!d'
      5
      4
      3
      2
      1
      # 1!G 第一行不执行把保持空间内容追加到模式空间,因为现在保持空间还没有数据
      # h 将模式空间放到保持空间暂存
      # $!d 最后一行不执行删除模式空间的内容。

      (5)每行后面添加新空行

      [root@openEuler-1 script]# seq 5 |sed G
      1
      
      2
      
      3
      
      4
      
      5
      
      

      [root@openEuler-1 script]#  echo -e "anAnbnc" |sed 's/a/1/Ig'
      1
      1
      b
      c
      

      [root@openEuler-1 script]# seq 10 |sed -n '$='
      10
      

      awk 是一个处理文本的编程语言工具,能用简短的程序处理标准输入或文件、数据排序、计算以及 生成报表等。

      基本的命令语法:awk option 'pattern {action}' file

      其中pattern表示AWK在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。花括号用于根据特定的模式对一系列指令进行分组。

      awk 处理的工作方式与数据库类似,支持对记录和字段处理,这也是grep和sed不能实现的。在awk中,缺省的情况下将文本文件中的一行视为一个记录,逐行放到内存中处理,而将一行中的某一部分作为记录中的一个字段。用1,2,3…数字的方式顺序的表示行(记录)中的不同字段。用$后跟数字,引用对应的字段,以逗号分隔,0表示整个行。

      (1)从文件读取awk程序处理文件

      [root@openEuler-1 script]# cat test.awk
      {print $2}
      [root@openEuler-1 script]# tail -n3 /etc/services | awk -f test.awk
      45514/udp
      45514/tcp
      46998/tcp
      

      (2)指定分隔符,打印指定字段(默认以空格分割)

      [root@openEuler-1 script]# tail -n3 /etc/passwd | awk -F':' '{print $1}'
      apache
      mysql
      nginx
      

      (3)指定多个分隔符作为同一个分隔符处理

      [root@openEuler-1 script]# tail -n3 /etc/services
      cloudcheck-ping 45514/udp               # ASSIA CloudCheck WiFi Management keepalive
      cloudcheck      45514/tcp               # ASSIA CloudCheck WiFi Management System
      spremotetablet  46998/tcp               # Capture handwritten signatures
      
      [root@openEuler-1 script]# tail -n3 /etc/services | awk -F'[/#]' '{print $1}'
      cloudcheck-ping 45514
      cloudcheck      45514
      spremotetablet  46998
      [root@openEuler-1 script]# tail -n3 /etc/services | awk -F'[/#]' '{print $2}'
      udp
      tcp
      tcp
      [root@openEuler-1 script]# tail -n3 /etc/services | awk -F'[/#]' '{print $3}'
       ASSIA CloudCheck WiFi Management keepalive
       ASSIA CloudCheck WiFi Management System
       Capture handwritten signatures
      
      

      (4)变量赋值

      [root@openEuler-1 script]# awk -v a=123 'BEGIN{print a}'
      123
      

      (5)输出awk全局变量到文件

      [root@openEuler-1 script]# seq 5 | awk --dump-variables '{print $0}'
      1
      2
      3
      4
      5
      [root@openEuler-1 script]# cat awkvars.out
      ARGC: 1
      ARGIND: 0
      ARGV: array, 1 elements
      BINMODE: 0
      CONVFMT: "%.6g"
      ENVIRON: array, 25 elements
      ERRNO: ""
      FIELDWIDTHS: ""
      FILENAME: "-"
      FNR: 5
      FPAT: "[^[:space:]]+"
      FS: " "
      FUNCTAB: array, 41 elements
      IGNORECASE: 0
      LINT: 0
      NF: 1
      NR: 5
      OFMT: "%.6g"
      OFS: " "
      ORS: "n"
      PREC: 53
      PROCINFO: array, 21 elements
      RLENGTH: 0
      ROUNDMODE: "N"
      RS: "n"
      RSTART: 0
      RT: "n"
      SUBSEP: "34"
      SYMTAB: array, 28 elements
      TEXTDOMAIN: "messages"
      

      (6)BEGIN和END

      BEGIN模式是在处理文件之前执行该操作,常用于修改内置变量、变量赋值和打印输出的页眉或标 题。END模式是在程序处理完才会执行。

      示例:

      [root@openEuler-1 script]# cat frequent_ip.sh
      #!/bin/bash
      #########################
      #File name:frequent_ip.sh
      #Email:obboda@163.com
      #Created time:2025-01-14 11:46:11
      #Description:访问nginx日志,得到访问ip最多的前10个
      #########################
      
      log_path="/var/log/nginx/access.log"
      
      # 拿取按照访问次数排序过的ip
      sort_data=`awk  '{print $1}'  /var/log/nginx/access.log | sort | uniq -c`
      
      
      # 按照sort_data的数据进行优化处理,打印输出
      echo "$sort_data" | awk '
      BEGIN{printf "%-10s %-10s %-10s n","访问排名","访问IP","访问次数"}
      {printf "%-10s %-20s %-10s n",NR,$2,$1}
      END{print "end............"}
      '
      [root@openEuler-1 script]# bash frequent_ip.sh
      访问排名       访问IP       访问次数
      1          192.168.121.1        8
      2          192.168.121.12       3
      3          192.168.121.13       2
      4          192.168.121.131      1
      5          192.168.121.51       4
      end............
      

      (1)FS和OFS

      在程序开始前重新赋值FS变量,改变默认分隔符为冒号,与-F一样。

      [root@openEuler-1 script]# head -n5 /etc/passwd | awk 'BEGIN{FS=":"}{print $1,$2}'
      root x
      bin x
      daemon x
      adm x
      lp x
      
      # 也可以使用-v来重新赋值这个变量,并指定输出分隔符
      [root@openEuler-1 script]# head -n5 /etc/passwd | awk -vFS=':'  '{print $1,$2}'
      root x
      bin x
      daemon x
      adm x
      lp x
      
      # 也可以指定输出分隔符
      [root@openEuler-1 script]# head -n5 /etc/passwd | awk 'BEGIN{FS=":";OFS="#"}{print $1,$2}'
      root#x
      bin#x
      daemon#x
      adm#x
      lp#x
      
      

      (2)RS和ORS

      # 指定以某个字符作为分隔符来处理记录:
      [root@openEuler-1 script]# echo "www.baidu.com/user/test.html" |awk 'BEGIN{RS="/"}{print $0}'
      www.baidu.com
      user
      test.html
      
      # 将输出的换行符替换为+号:
      [root@openEuler-1 script]# seq 10 | awk 'BEGIN{ORS="+"}{print $0}'
      1+2+3+4+5+6+7+8+9+10+[root@openEuler-1 script]#

      (3)NF

      # NF是字段个数
      [root@openEuler-1 script]# echo "a b c d e f" | awk '{print NF}'
      6
      
      # 打印最后一个字段
      [root@openEuler-1 script]# echo "a b c d e f" | awk '{print $NF}'
      f
      

      (4)NR和FNR

      NR统计记录编号,每处理一行记录,编号就会+1,FNR不同的是在统计第二个文件时会重新计数。

      [root@openEuler-1 script]# tail -n5 /etc/services | awk '{print NR,$0}'
      1 axio-disc       35100/udp               # Axiomatic discovery protocol
      2 pmwebapi        44323/tcp               # Performance Co-Pilot client HTTP API
      3 cloudcheck-ping 45514/udp               # ASSIA CloudCheck WiFi Management keepalive
      4 cloudcheck      45514/tcp               # ASSIA CloudCheck WiFi Management System
      5 spremotetablet  46998/tcp               # Capture handwritten signatures
      

      NR和FNR的区别:

      [root@openEuler-1 script]# awk '{print NR,FNR,$0}' a b
      1 1 a
      2 2 b
      3 3 c
      4 1 d
      5 2 e
      6 3 f
      

      (5)ARGC和ARGV

      ARGC是命令行参数数量

      ARGV是将命令行参数存到数组,元素由ARGC指定,数组下标从0开始

      [root@openEuler-1 script]# awk 'BEGIN{print ARGC}' 1 2 3
      4
      [root@openEuler-1 script]# awk 'BEGIN{print ARGV[0],ARGV[1]}' 1 2 3
      awk 1
      

      (6)ARGIND

      ARGIND是当前正在处理的文件索引值,第一个文件是1,第二个文件是2,以此类推,从而可以通过这种方式判断正在处理哪个文件。

      [root@openEuler-1 script]# awk '{print ARGIND,$0}' a b
      1 a
      1 b
      1 c
      2 d
      2 e
      2 f
      

      (7)ENVIRON

      ENVIRON调用系统变量。

      [root@openEuler-1 script]# awk 'BEGIN{print ENVIRON["HOME"]}'
      /root
      

      (8)FILENAME

      FILENAME是当前处理文件的文件名。

      [root@openEuler-1 script]# awk '{print FILENAME,$0}' a b
      a a
      a b
      a c
      b d
      b e
      b f
      

      (9)IGNORECASE

      IGNORECASE=1表示忽略大小写

      [root@openEuler-1 script]# echo "A a b c" |xargs -n1 |awk 'BEGIN{IGNORECASE=1}/a/'
      A
      a
      

      注意:在awk中,有3种情况表达式为假:数字是0,空字符串和未定义的值。且数值运算,未定义变量初始值为0。字符运算,未定义变量初始值为空。

      (1)截取整数

      [root@openEuler-1 script]# echo "123abc abc123 123abc123" |xargs -n1 | awk '{print +$0}'
      123
      0
      123
      
      [root@openEuler-1 script]# echo "123abc abc123 123abc123" |xargs -n1 | awk '{print -$0}'
      -123
      0
      -123

      (2)打印奇数偶数行

      # 打印奇数行
      [root@openEuler-1 script]# seq 6 | awk 'i=!i'
      1
      3
      5
      
      # 打印偶数行
      [root@openEuler-1 script]# seq 6 | awk '!(i=!i)'
      2
      4
      6
      

      (3)管道符的使用

      [root@openEuler-1 script]# seq 5 | shuf | awk '{print $0|"sort"}'
      1
      2
      3
      4
      5
      # 其中shuf会将原来的顺序打乱

      (4)三目运算符

      [root@openEuler-1 script]# awk 'BEGIN{print 1==1?"yes":"no"}'
      yes
      

      (1)if语句

      格式:if (condition) statement [ else statement ]

      # 单分支
      [root@openEuler-1 script]# seq 5 | awk '{if($0==3)print $0}'
      3
      
      # 双分支
      [root@openEuler-1 script]# seq 5 |awk '{if($0==3)print $0;else print "no"}'
      no
      no
      3
      no
      no
      

      (2)while语句

      格式:while (condition) statement

      [root@openEuler-1 script]# echo "1 2 3 4 5" | awk '{i=1;while(i<=NF){print $i;i++}}'
      1
      2
      3
      4
      5
      

      (3)for语句C语言风格

      格式:for (expr1; expr2; expr3) statement

      [root@openEuler-1 script]# cat file
      1 2 3
      4 5 6
      7 8 9
      [root@openEuler-1 script]# awk '{for(i=1;i<=NF;i++)print $i}' file
      1
      2
      3
      4
      5
      6
      7
      8
      9
      

      (4)for语句遍历数组

      格式:for (var in array) statement

      [root@openEuler-1 script]# seq -f "str%.g" 5 |awk '{a[NR]=$0}END{for(v in a)print v,a[v]}'
      1 str1
      2 str2
      3 str3
      4 str4
      5 str5
      

      (5)break和continue语句

      break跳过所有循环,continue跳过当前循环。

      [root@openEuler-1 script]# awk 'BEGIN{for(i=1;i<=5;i++){if(i==3){break};print i}}'
      1
      2
      [root@openEuler-1 script]# awk 'BEGIN{for(i=1;i<=5;i++){if(i==3){continue};print i}}'
      1
      2
      4
      5
      

      (6)exit语句

      格式:exit [ expression ]

      exit退出程序,与shell的exit一样。[ expr ]是0-255之间的数字。

      [root@openEuler-1 script]# seq 5 |awk '{if($0~/3/)exit (123)}'
      [root@openEuler-1 script]# echo $?
      123
      

      [root@openEuler-1 script]# cat c
      123abc
      abc123
      123abc123
      [root@openEuler-1 script]# awk '{print int($0)}' c
      123
      0
      123
      

      # 获取匹配行的下一行
      [root@openEuler-1 script]# seq 5 |awk '/3/{getline;print}'
      4
      

      格式化输出,默认打印字符串不换行。

      格式:printf [format] arguments

      # 左对齐宽度10
      [root@openEuler-1 script]# awk 'BEGIN{printf "%-10s %-10s %-10sn","ID","Name","Passwd"}'
      ID         Name       Passwd
      

      到此这篇关于Shell正则表达式与文本处理三剑客grep、sed、awk的文章就介绍到这了,更多相关Shell正则表达式grep、sed、awk内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

      您可能感兴趣的文章:

      • Shell正则表达式之grep、sed、awk实操笔记
      • Shell中使用grep、sed正则提取和替换字符串
      • shell脚本之正则表达式、grep、sed、awk
      • shell正则表达式、grep命令和sed命令举例详解
      • shell正则表达式智能匹配、grep智慧过滤工具、sed基本用法、sed基本操作指令实例代码

      站内搜索