文本三剑客

  • grep:文本过滤(模式:pattern)工具
    grep, egrep, fgrep(不支持正则表达式搜索)
  • sed:stream editor,文本编辑工具
  • awk:Linux上的实现gawk,文本报告生成器

grep

介绍

  • grep: Global search REgular expression and Print out the line

    • 作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行
  • 模式:由正则表达式字符及文本字符所编写的过滤条件

  • grep [OPTIONS] PATTERN [FILE…]

    • grep root /etc/passwd
    • grep "$USER" /etc/passwd grep '$USER' /etc/passwd
    • grep $(whoami) /etc/passwd

选项

  • –color=auto: 对匹配到的文本着色显示

  • -m # 匹配#次后停止

  • -v 显示不被pattern匹配到的行

  • -i 忽略字符大小写

  • -n 显示匹配的行号

  • -c 统计匹配的行数

  • -o 仅显示匹配到的字符串

  • -q 静默模式,不输出任何信息

  • -A # after, 后#行

  • -B # before, 前#行

  • -C # context, 前后各#行

  • -e 实现多个选项间的逻辑or关系
    grep –e 'cat' -e 'dog' file

  • -w 匹配整个单词

  • -E 使用egrep

  • -F 相当于fgrep,不支持正则表达式

  • -f file 根据模式文件处理

示例

1.显示/proc/meminfo文件中以大小s开头的行(2种方式)
reg: ^[Ss]
grep "^[Ss]" /proc/meminfo
grep -i "^s" /proc/meminfo

2.显示/etc/passwd文件中不以/bin/bash结尾的行
reg: /bin/bash$
grep -v "/bin/bash$" /etc/passwd

3.如果root用户存在,显示其默认的shell程序 位置锚定
[root@test tmp]# id root > /dev/null && grep "^root\>" /etc/passwd | cut -d: -f7

4.找出/etc/passwd中的两位或三位数 ; 贪婪匹配 –> 继续往后匹配
reg: [[:digit:]]\{2,3\}
[root@test tmp]# grep "\<[[:digit:]]\{2,3\}\>" /etc/passwd
[root@test tmp]# grep "\<[0-9]\{2,3\}\>" /etc/passwd
[root@test tmp]# grep -E "\<[0-9]{2,3}\>" /etc/passwd – 使用ERE

5.显示/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面存非空白字符行
reg : ^[[:space:]]\+[^[:space:]]\+
[root@test tmp]# grep "^[[:space:]]\+[^[:space:]]\+" /etc/grub2.cfg

6.找出“netstat -tan”命令的结果中以’LISTEN’后跟0、1或多个空白字符结尾的行
reg: LISTEN[[:space:]]*$
netstat -tan | grep "LISTEN[[:space:]]*$"

7.添加用户bash、testbash以及nologin(其shell为/sbin/nologin),然后找出/etc/passwd文件中用户名同shell名的行
useradd bash && useradd testbash && useradd nologin -s /sbin/nologin
bash:x:1010:1013::/home/bash:/bin/bash
nologin:x:1012:1015::/home/nologin:/sbin/nologin
reg: [[:alnum:]]\+
扩展正则:
[root@test tmp]# grep -E "^(\<[[:alnum:]]+\>).*\1$" /etc/passwd
基本正则:
[root@test tmp]# grep "^\(\<[[:alnum:]]\+\>\).*\1$" /etc/passwd

\1 : 引用分组的内容;保证用户名和shell同名

sed

介绍

  • Stream EDitor, 行编辑器
  • sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。然后读入下行,执行下一个循环。如果没有使诸如‘D’的特殊命令,那会在两个循环之间清空模式空间,但不会清空保留空间。这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
  • 功能:主要用来自动编辑一个或多个文件,简化对文件的反复操作,编写转换程序等
  • 参考: http://www.gnu.org/software/sed/manual/sed.html

用法

sed [option]... 'script' inputfile...

  • 常用选项:

    • -n 只打印匹配到的行
    • -e 多点编辑
    • -f /PATH/SCRIPT_FILE 从指定文件中读取编辑脚本
    • -r 支持使用扩展正则表达式
    • -i.bak 备份文件并原处编辑
  • script:

    • ‘地址命令’
  • 地址定界:

    • 不给地址:对全文进行处理

    • 单地址:

      • #:指定的行,$:最后一行

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

    • 地址范围:

      • x,y 从x行到y行

      • x;y 第x行和第y行

      • x,+y x后y行

      • x,y! : 从x,y行之外

      • /pat1/,/pat2/ 查询包含两个模式的行

      • #,/pat1/ #行后查询包含匹配模式的行

      • /pat1/,# #行内查询包含匹配模式的行

    • ~:步进, 第一个数为起始行后一个数字为前进步数

      • 1~2 奇数行
      • 2~2 偶数行
  • 编辑命令:

    • d 删除模式空间匹配的行,并立即启用下一轮循环
    • p 打印当前模式空间内容,追加到默认输出之后
    • a [\]text 在指定行后面追加文本,支持使用\n实现多行追加
    • i [\]text 在行前面插入文本
    • c [\]text 替换行为单行或多行文本
    • w /path/file 保存模式匹配的行至指定文件
    • r /path/file 读取指定文件的文本至模式空间中匹配到的行后
    • = 为模式空间中的行打印行号
    • ! 模式空间中匹配行取反处理
  • 高级编辑命令:

    • P: 打印模式空间开端至\n内容,并追加到默认输出之前
    • h: 把模式空间中的内容覆盖至保持空间中
    • H:把模式空间中的内容追加至保持空间中
    • g: 从保持空间取出数据覆盖至模式空间
    • G:从保持空间取出内容追加至模式空间
    • x: 把模式空间中的内容与保持空间中的内容进行互换
    • n: 读取匹配到的行的下一行覆盖至模式空间
    • N:读取匹配到的行的下一行追加至模式空间
    • D:如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,
      并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间
      不包含换行符,则会像发出d命令那样启动正常的新循环
    • q: 第一个模式匹配后立即退出
    • {}: 在定位执行行的命令组,用;进行分隔
  • s/// 查找替换,支持使用其它分隔符,s@@@,s###

  • 替换标记:

    • g 行内全局替换
    • p 显示替换成功的行
    • w /PATH/FILE 将替换成功的行保存至文件中
  • 注意: -i 和 -n 不能一起使用

示例

  • sed ‘2p’ /etc/passwd 显示/etc/passwd的第2行

  • sed -n ‘2p’ /etc/passwd 不显示/etc/passwd的第2行

  • sed -n ‘1,4p’ /etc/passwd

  • sed -n ‘/root/p’ /etc/passwd

  • sed -n ‘2,/root/p’ /etc/passwd 从2行开始

  • sed -n ‘/^$/=’ file 显示空行行号

  • sed -n -e ‘/^\$/p’ -e ‘/^$/=’ file

  • sed‘/root/a\superman’ /etc/passwd行后

  • sed ‘/root/i\superman’ /etc/passwd 行前

  • sed ‘/root/c\superman’ /etc/passwd 代替行

  • sed ‘/^$/d’ file

  • sed ‘1,10d’ file

  • nl /etc/passwd | sed ‘2,5d’

  • nl /etc/passwd | sed ‘2a tea’

  • sed 's/test/mytest/g' example

  • sed –n ‘s/root/&superman/p’ /etc/passwd 单词后

  • sed –n ‘s/root/superman&/p’ /etc/passwd 单词前

  • sed -e ‘s/dog/cat/’ -e ‘s/hi/lo/’ pets

  • sed –i.bak ‘s/dog/cat/g’ pets

  • sed -n 'n;p' FILE

  • sed '1!G;h;\$!d' FILE

  • sed ‘N;D’FILE

  • sed '$!N;$!D' FILE

  • sed '$!d' FILE

  • sed ‘G’ FILE

  • sed ‘g’ FILE

  • sed ‘/^$/d;G’ FILE

  • sed 'n;d' FILE

  • sed -n '1!G;h;$p' FILE

  • ls test*.txt|sed -r 's#(.*)txt#mv & \1jpg#g'

  • 只打印文本的第1到4行内容
    [root@test tmp]# sed -n '1,4p' fstab

  • 只打印文本中包含xfs的行
    [root@test tmp]# sed -n '/xfs/p' fstab

  • 只打印文本中以UUID开头的行
    [root@test tmp]# sed -n '/^UUID=.*/p' fstab

  • 显示文件中以UUID开头行的行号
    [root@test tmp]# sed -n '/^UUID=.*/=' fstab

  • 在/etc/hosts文件中第3行位置添加主机名解析内容
    [root@test tmp]# sed -i '2a\192.168.10.10 node1' /etc/hosts

  • 删除上述添加的解析内容
    [root@test tmp]# sed -i '3d' /etc/hosts

  • 替换以UUID开头行的内容
    [root@test tmp]# sed -i '/^UUID=.*/c\test......' fstab

  • 将fstab文件中以#开头的所有内容保存至fstab_part文件中
    [root@test tmp]# sed '/^#.*/w fstab_part' fstab

  • 将fstab_part文件内容读写到1.txt文件中第2行以后位置
    [root@test tmp]# sed -i '2r fstab_part' 1.txt

  • 将1.txt文本中hello替换成全局替换成大写
    [root@test tmp]# sed -i 's/hello/HELLO/g' 1.txt

  • 将替换的内容保存至1_part.txt文本中
    [root@test tmp]# sed 's/HELLO/Hi/g w 1_part.txt' 1.txt

  • 显示/etc/passwd文件中位于第偶数行的用户的用户名
    sed -n 'n;p' /etc/passwd | cut -d: -f1

  • 为/tmp/1.txt 文件中前三行的行首加#号。
    sed -i '1,3s@\(^.\)@#\1@g' /tmp/grub.conf
    1,3s@\(^.\)@#\1@g
    sed "1,3s/(.*)/#\1/"

  • 取消注释行:
    sed '1,10s@^#\(.*\)$@\1@g' 1.txt

    ^#+(.*)$ —> 查询内容:所有#开头的行

    \1 替换的内容 (.*)

awk

awk介绍

  • awk:Aho, Weinberger, Kernighan,报告生成器,格式化文本输出
  • 有多种版本:New awk(nawk),GNU awk( gawk)
  • gawk:模式扫描和处理语言
  • 基本用法:
    • awk [options] ‘program’ var=value file…
    • awk [options] -f programfile var=value file…
    • awk [options] ‘BEGIN{action;… }pattern{action;… }END{action;… }’ file …
    • awk 程序可由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成
    • program 通常是被放在单引号中
  • 选项:
    • -F “分隔符” 指明输入时用到的字段分隔符
    • -v var=value 变量赋值

awk语言

  • 基本格式:awk [options] ‘program’ file…
  • Program:pattern{action statements;..}
  • pattern和action
    • pattern部分决定动作语句何时触发及触发事件
      BEGIN,END
    • action statements对数据进行处理,放在{}内指明
      print, printf
  • 分割符、域和记录
    • awk执行时,由分隔符分隔的字段(域)标记$1,$2…$n称为域标识。$0为所有域,注意:此时和shell中变量$符含义不同
    • 文件的每一行称为记录
    • 省略action,则默认执行 print $0 的操作

awk工作原理

  • 第一步:执行BEGIN{action;… }语句块中的语句
  • 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
  • 第三步:当读至输入流末尾时,执行END{action;…}语句块
  • BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
  • END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
  • pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块

awk变量

  • 变量:内置和自定义变量
  • 自定义变量(区分字符大小写)
    • -v var=value
    • 在program中直接定义
  • FS:输入字段分隔符,默认为空白字符
    • awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd
    • awk –F: '{print $1,$3,$7}’ /etc/passwd
  • OFS:输出字段分隔符,默认为空白字符
    • awk -v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’ /etc/passwd
  • RS:输入记录分隔符,指定输入时的换行符
    • awk -v RS=' ' ‘{print }’ /etc/passwd
  • ORS:输出记录分隔符,输出时用指定符号代替换行符
    • awk -v RS=' ' -v ORS='###'‘{print }’ /etc/passwd
  • NF:字段数量(列)
    • awk -F:‘{print NF}’ /etc/fstab 引用变量时,变量前不需加$
    • awk -F:‘{print $(NF-1)}' /etc/passwd
  • NR:记录号(行)
    • awk ‘{print NR}’ /etc/fstab ; awk END‘{print NR}’ /etc/fstab
  • FNR:各文件分别计数,记录号
    • awk '{print FNR}' /etc/fstab /etc/inittab
  • FILENAME:当前文件名
    • awk '{print FILENAME}’ /etc/fstab
  • ARGC:命令行参数的个数
    • awk '{print ARGC}’ /etc/fstab /etc/inittab
    • awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab
  • ARGV:数组,保存的是命令行所给定的各参数
    • awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab
    • awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab
  • 示例:
    • awk -v test='hello gawk' '{print test}' /etc/fstab
    • awk -v test='hello gawk' 'BEGIN{print test}'
    • awk 'BEGIN{test="hello,gawk";print test}'
    • awk -F:‘{sex=“male”;print $1,sex,age;age=18}’ /etc/passwd cat awkscript {print script,$1,$2}
    • awk -F: -f awkscript script=“awk” /etc/passwd
  • print格式:print item1, item2, …
  • 要点:
    (1) 逗号分隔符
    (2) 输出item可以字符串,也可是数值;当前记录的字段、变量或awk的表达式
    (3) 如省略item,相当于print $0
  • 示例:
    • awk '{print "hello,awk"}'
    • awk –F: '{print}' /etc/passwd
    • awk –F: ‘{print “kong”}’ /etc/passwd
    • awk –F: ‘{print $1}’ /etc/passwd
    • awk –F: ‘{print $0}’ /etc/passwd
    • awk –F: ‘{print $1”\t”$3}’ /etc/passwd
    • grep “^UUID”/etc/fstab| awk ‘{print $2,$4}’

  • 格式化输出:printf “FORMAT”, item1, item2, …
    (1) 必须指定FORMAT
    (2) 不会自动换行,需要显式给出换行控制符,\n
    (3) FORMAT中需要分别为后面每个item指定格式符

  • 格式符:与item一一对应

    • %c:显示字符的ASCII码
    • %d, %i:显示十进制整数
    • %e, %E:显示科学计数法数值
    • %f:显示为浮点数
    • %g, %G:以科学计数法或浮点形式显示数值
    • %s:显示字符串
    • %u:无符号整数
    • %%:显示%自身
  • 修饰符

    • #[.#] 第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
    • - 左对齐(默认右对齐) %-15s
    • + 显示数值的正负符号 %+d
  • 示例

    • awk -F: ‘{printf "%s",$1}’ /etc/passwd
    • awk -F: ‘{printf "%s\n",$1}’ /etc/passwd
    • awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
    • awk -F:‘ {printf "Username: %s\n",$1}’ /etc/passwd
    • awk -F: ‘{printf “Username: %s,UID:%d\n",$1,$3}’ /etc/passwd
    • awk -F: ‘{printf "Username: %15s,UID:%d\n",$1,$3}’ /etc/passwd
    • awk -F: ‘{printf "Username: %-15s,UID:%d\n",$1,$3}’/etc/passwd

操作符

  • 算术操作符:

    • x+y, x-y, x*y, x/y, x^y, x%y
    • -x:转换为负数
    • +x:将字符串转换为数值
  • 字符串操作符:没有符号的操作符,字符串连接

  • 赋值操作符:
    =, +=, -=, *=, /=, %=, ^=,++, –

  • 比较操作符:
    ==, !=, >, >=, <, <=

  • 模式匹配符:

    • ~:左边是否和右边匹配,包含
    • !~:是否不匹配
    • 示例:
      • awk -F: '$0 ~ /root/{print $1}‘ /etc/passwd
      • awk '$0~“^root"' /etc/passwd
      • awk '$0 !~ /root/‘ /etc/passwd
      • awk -F: ‘$3==0’ /etc/passwd
  • 逻辑操作符:与&&,或||,非!
    示例:

    • awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
    • awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
    • awk -F: ‘!($3==0) {print $1}' /etc/passwd
    • awk -F: ‘!($3>=500) {print $3}’ /etc/passwd
  • 条件表达式(三目表达式)

    selector?if-true-expression:if-false-expression
    示例:

    awk -F: '{$3>=1000?usertype="Common User":usertype=" SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd

awk PATTERN

  • PATTERN:根据pattern条件,过滤匹配的行,再做处理

    (1)如果未指定:空模式,匹配每一行

    (2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来

    • awk'/^UUID/{print $1}' /etc/fstab
    • awk'!/^UUID/{print $1}' /etc/fstab

    (3) relational expression: 关系表达式,结果为“真”才会被处理

    • 真:结果为非0值,非空字符串

    • 假:结果为空字符串或0值

      示例:

      • awk -F: 'i=1;j=1{print i,j}' /etc/passwd
      • awk ‘!0’ /etc/passwd ; awk‘!1’ /etc/passwd
      • awk -F: '$3>=1000{print $1,$3}' /etc/passwd
      • awk-F: '$3<1000{print $1,$3}' /etc/passwd
      • awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
      • awk -F: '$NF ~ /bash$/{print $1,$NF}' /etc/passwd

    (4) line ranges:行范围

    • startline,endline:/pat1/,/pat2/ 不支持直接给出数字格式
    • awk -F: ‘/^root\>/,/^nobody\>/{print $1}' /etc/passwd
    • awk -F: ‘(NR>=10&&NR<=20){print NR,$1}' /etc/passwd

    (5) BEGIN/END模式

    • BEGIN{}:仅在开始处理文件中的文本之前执行一次

    • END{}:仅在文本处理完成之后执行一次

      示例:

      • awk -F : ‘BEGIN {print “USER USERID”} {print $1“:”$3} END{print “END FILE"}' /etc/passwd

      • awk -F : '{print "USER USERID“;print $1":"$3} END{print "END FILE"}' /etc/passwd

      • awk -F: 'BEGIN{print " USER UID \n--------------- "}{print $1,$3}' /etc/passwd

      • awk -F: ‘BEGIN{print “ USER UID \n--------------- ”}{print $1,$3}’END{print “==============”} /etc/passwd

      • seq 10 | awk 'i=0'

      • seq 10 | awk 'i=1'

      • seq 10 | awk 'i=!i'

      • seq 10 | awk'{i=!i;print i}'

      • seq 10 | awk‘!(i=!i)'

      • seq 10 | awk-v i=1 'i=!i'

awk action

  • 常用的action分类

    (1) Expressions:算术,比较表达式等

    (2) Control statements:if, while等

    (3) Compound statements:组合语句

    (4) input statements

    (5) output statements:print等

更多请参看https://www.runoob.com/w3cnote/awk-built-in-functions.html#b2