grep/sed/awk三剑客

发布时间 2023-07-15 14:35:53作者: 枫飘过的天1

1.grep正则表达式
   (1)egrep使用
       正则表达式(regular express;使用一串符号,描述有共同属性的数据
       egrep测试工具(同grep -e):egrep 选项 '正则表达式' 文件
       命令|egrep 选项 '正则表达式'
       -i 忽略大小写 -v 取反 -c 统计匹配行数
       -q 静默输出 -n 显示行号
       基本元字符
       ^ 匹配行首(^abc 以abc开头的行)
       $ 匹配行尾(abc$ 以abc结尾的行) --^$ 空行
       . 单个字符(除换行符\n外任意单个字符)
       + 最少匹配一次((abc)+ 一个或多个连续的abc)
       ? 最多匹配一次 ((abc)? 0或1个abc)
       * 匹配任意次数((abc)* 0或多个连续的abc) .* 匹配任意字符串
       {}限定表达式匹配次数
       {n} 匹配n次 (ab){3} -->匹配ababab
       {n,m} 匹配n-m次 (ab){1,3} -->匹配ab abab ababab
       {n,} 匹配至少n次 (ab){2,} -->匹配2个及以上连续的ab
       []匹配指定范围内的单个字符,[]内加^可取反
       [a-z] 匹配任意小写字母 [A-Z] 匹配任意大写字母
       [0-9] 匹配任意数字 [a-Z0-9] 匹配任意字母或数字
       [alc45_?] 匹配a、l、c、4、5、_、?
       [^A-Z] 匹配非大写字母的行 [^a-z] 匹配非小写字母的行
       例子:
       egrep '(abc)+' a.txt --匹配abc至少一次
       egrep '(abc){2}' a.txt --匹配abcabc的行
       egrep '^[^a-z]' a.txt --匹配非小写字母开头的行

   (2)其他元字符:
       () 组合为整体 ab{1,3} 匹配ab/abb/abbb(或(ab){1,3} 匹配ab/abab/ababab)
       | 或者 root|bin 匹配root或bin
       \b 单词的边界 \broot\b 匹配root、不匹配keroot/rooty/brooty
       \< 单词的开头 \<th 匹配以th开头的单词
       \> 单词的结束 \<root\> 匹配root,与\broot\b 相同

       grep '^\<root\>' /etc/passwd 列出以root单词单头的记录

2.awk正则表达式
   (1)awk过滤
       非交互处理:
       重定向、管道、命令替换、字符串截取(shell内建机制)
       grep行检测、expr/cut字符串切割、tr字符替换、awk/sed专用工具(检索和过滤工具)
       awk与sed:被称为非交互处理的“瑞士军刀”

       awk:基于模式匹配,逐行处理并print结果(过滤)
       sed:基于匹配过滤机修改文本,逐行处理并将结果输出到屏幕
       可实现过滤、删除、替换、复制、剪切,以及导入/导出等各种操作

       awk文本过滤基本用法:
       命令|awk '[选项] '[条件]{编辑命令}'
       awk '[选项] '[条件]{编辑命令}' 文件.... (若多条语句,可用分号分隔;print是最常用命令)

       常用命令选项:
       -F 指定分隔符,可省略(默认空格或tab位)
       -f 调用awk脚本进程处理
       awk内置变量:(特殊含义,可直接使用)
       FS 保存或设置字段分隔符,FS=":"
       $n 指定分隔的第几个字段,如$1/$3 第1/3列
       $0 当前读取的整行内容
       NF 列数
       NR 行数
       FNR 行号
       FILENAME 当前处理的文件名
       ENVIRON 调用shell环境变量,格式:ENVIRON["变量名"]

       awk '{print "第"FNR"行","有"NF"列"}' /etc/paaswd --查看每行有多少列
       awk '{print "Last:"$NF}' a.txt --输出每行最后一个字段
       awk -F: '$1==ENVIRON["USER"]{print $3}' /etc/passwd   --输出当前用户的UID信息
       awk -F: '{print $1","$3}' pass.txt --打印第1/3列,用逗号隔开
       awk '{print $1}' a.txt --打印第一列
       awk -F ":" '{print $1,$2}' /etc/passwd (-F 指定分隔符,$1/$2 第一列、第二列)

       awk处理时机:(可同时使用或单独使用)
       行前处理:BEGIN{},读入第一行文本之前的执行,一般用于初始化操作
       逐行处理:{},逐行读入文本执行相应的处理,最常用
       行后处理:END{},处理完最后一行文本后执行,一般用于输出处理结果

       例子:
       awk "BEGIN{a=34.56;print a+12}" 结果46.56.--预处理,不需要数据文件(可支持小数运算)
       awk 'BEGIN{x=0}/\<bash$/{x++} END{print x}' /etc/passwd 结果59
       --统计bash的用户个数
       awk 'BEGIN {print NR} END{print NR}' /etc/passwd
       0 --预处理,行数为0
       2 --全部处理完后,行数已读入文本的行数

       awk正则条件:
       /正则表达式/ ~ 匹配 !~ 不匹配
       awk -F: '/^ro/' a.txt --列出ro开头的行
       awk -F: '$7!~/bash$/{print $1,$7}' /etc/passwd
       --列出第7个字段,不以bash结尾的用户名
       数值比较:
       == 等于 != 不等 >大于 >= 大于等于 < 小于 <= 小于等于
       逻辑比较测试:&& 逻辑与 || 逻辑或
       运算符:+ - * / % ++ -- += -= *= /=

       awk 'NR%2==1{print}' a.txt //输出奇数行文本
       awk 'BEGIN{i=1}{i+=NF} END{print}' a.txt --统计文本的总字段个数
       seq 200|awk 'BEGIN{i=0}($0%3==0)&&($0%13==0){i++} END{print}}'
       统计能同时被3/13整除的整数
       awk 'NR==2{print}' a.txt --输出第二行
       awk '$2!="XX"{print}' a.txt --输出第二列不是XX的行
       awk 'NF>=2{print}' a.txt --输出包含2个及以上字段的行(打印列数大于2的行)
       awk -F: '$3>=0&&$3<2{print $1,$3}' /etc/passwd --列出UID小于2的用户信息
       awk -F: '$3==1||$3==7{print $1,$3}'/etc/passwd --列出UID为2和7的用户信息

       awk中if分支结构:
       单分支:if(条件){编辑指令}
       双分支:if(条件){编辑指令1}else{编辑指令2}
       多分支:if(条件){编辑指令1}else if(条件){编辑指令2}...
       else{编辑指令n}

       while循环结构
       while循环: while(条件){编辑命令}
       do while循环: do{编辑指令}while(条件)

       for循环结构:
       for(初值;条件;步长){编辑指令}
       awk 'BEGIN{for(i=1;i<=5;i++){print i}}' --打印1-5

       awk流程控制:
       break 结束当前循环
       continue 终止本次循环,转入下一次循环
       next 跳过当前行,读入下一行文本开始处理
       exit 结束文本读入,转入END{}

       例1:统计UID小于或等于500的用户个数,统计UID大于500的用户个数
       awk -F: 'BEGIN{i=0;j=0}{if($3<=500){i++}else{j++}}END{print i,j}' /etc/passwd
       例2:统计/etc/passwd文件内root出现次数(利用-F [:/] 分隔符为/或:)
       awk -F [:/] '{i=1}{while(i<=NF) {if($i~/root/){j++};i++}} END{print j}' /etc/passwd
       例子:输出包含2个及以上字段的行(跳过空行和只有1个字段的行)
       awk 'NF<2{next}{print}' a.txt
       awk '{if(NF>=2){print}}' a.sh(相当于if限定条件)

3.sed正则表达式
       前置命令|sed 选项 '编辑命令'
       sed 选项 '编辑指令' 文件....
       -n 屏蔽默认输出(过滤文本需添加) -i 直接修改文件内容
       -f 使用sed脚本 -e 指定多个处理动作
       -r 启用拓展正则表达式
       {} 可组合多个指令,用分号分隔
       地址符:(可理解为条件)
       /匹配内容/ -- 匹配内容
       基本处理动作:
       p 打印行(2,4p 输出2-4行 2p;4p 输出第2、第4行)
       d 删除行(2,4d 删除2-4行)
       s 字符串替换
       s/old/new/ 每行第一个替换
       s/old/new/3 每行第3个替换
       s/old/new/g 每行替换所有
       输出行:
       sed -n '2,4p' /etc/hosts 列印2-4行
       sed -n '/^bin/p' a.txt 输出bin开头的行
       sed -n 'n;p' a.txt 输出偶数行(n表示隔行,跳一行)
       sed -n 'p;n' a.txt 输出奇数行(n隔行)
       sed -n '10,${n;p}' a.txt 输出第10行至文件末尾所有偶数行
       sed -n '$=' a.txt --输出文件的行数($= 文件的行数)

       例子:cat -n /etc/inittab|sed -n '4,7p' --打印4-7行
       删除文本:
       '3,5d' --删除3-5行
       '/xml/d' --删除所有包行xml的行
       '/xml/!d' --不删除包含xml的行
       '$d' --删除文件最后一行
       '/^$/d' --删除所有空白行
       sed '/^$/{n;/^$/d}' --删除重复行,连续两个空行保留一行

       替换文本:
       sed 's/doc/&s/g' a.txt --将所有doc替换成docs,&代表查找的串
       注释指定行: sed '4,7s/^/#/' a.txt --注释4-7行
       去掉#注释行: sed 's/^#an/an/' a.txt --取消注释#an开头的行

       应用:找到/etc/inittab文件中以ID开头的行,将运行界别数值替换为3
       sed -i '//^id/s/[0-6]/3/' /etc/inittab
       将/var/www/html 修改为/opt/wwwroot
       sed -i 's#/var/www/html#/opt/wwroot#' /etc/httpd/conf/httpd.conf
       (s#old#new# 效果相当与s/old/new/ )

       sed文件块处理动作:
       i 行前插入文本 (2iYY 第2行之前插入文本行YY 4,7YY 在第4-7行每一行前添加文本行
       a 行后插入文本(2aYY 第2行之后添加文本 /^XX/aYY 在以XX开头的行后添加文本 )
       c 替换行前行 (2cYY 将第二行替换成YY)

       处理多行文本:
       以换行符\n分隔;或者\强制换行
       sed '3aAAAAA\nAAAAAAA' a.txt --第三行后添加,\n换行

       导入导出操作:
       -r 读取文件
       -w 保存到文件(覆盖) ---相当于>

       3r b.txt 在第3行下方插入文件b.txt
       4,7r b.txt 在第4-7行每行后插入文件b.txt
       3w c.txt 将第三行另存为文件c.txt
       4,7w c.txt 将4-7行另存为c.txt
       sed '2r m.txt' a.txt --在a.txt第二行后插入m.txt
       sed '/^ab/r m.txt' a.txt --将查到条件保存到指定文件m.txt
       sed -n '1,2w c.txt' a.txt
       sed -n '/^XX/w d.txt' a.txt

       sed复制剪切:
       缓存区域:
       模式空间:正在处理的内容
       保持空间:类似剪切板,默认存放一个空行(换行符\n)
       H 模式空间--》保持空间,复制、追加
       h 模式空间--》保持空间,复制、覆盖
       G 保持空间--》模式空间,粘贴、追加
       h 保持空间--》模式空间,粘贴、覆盖

       例子:把1-3行复制到文件末尾
       sed '1,3H;$G' a.txt
       把第一行剪切到文件末尾,把第1-2行剪切到文件末尾
       sed '1h;1d;$G' a.txt

4.awk/sed组合使用
       数组:一组数值,共同的名称、不同的标签不同的值
       数组定义: 数组名[下标]=元素值
       调用:数组名[下标]
       遍历数组: for (变量 in 数组名){print 数组名[变量]}
       为数组name复制两个元素,值jim/tom
       awk 'BEGIN{name[0]="jim";name[1]="tom";print name[0],name[1]}'

       awk 'BEGIN{ip[1]="192.168.8.129";ip[2]="192.168.8.130";print ip[2]}'
       awk 'BEGIN{ip["mail"]="192.168.8.129";ip["web"]="192.168.8.130";print ip[web],ip[mail]}'
       遍历数组:
       awk 'BEGIN{ip["1"]="192.168.8.129";ip["2"]="192.168.8.130";for(x in ip){print ip[x]}}'

       awk去重应用:去除重复行
       awk '!a[$0]++' a.txt --去除重复行(更方便),不需要排序,保留原来顺序
       (! 取反 ++ 递增运算 a数组名称,可任意变)

       去除重复字段:(指定字段就行了)
       awk -F: '!a[$7]++{print $7}' /etc/passwd