欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

shell-awk详细笔记

发布时间:2024/7/5 编程问答 26 豆豆
生活随笔 收集整理的这篇文章主要介绍了 shell-awk详细笔记 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
shell# var="hexiaoqiang"# ${var//PATTERN/SUBSTI}:查找var所表示的字符串中,所有被PATTERN所匹配到的字符串,并将其全部替换为SUBSTI所表示的字符串;${var/#PATTERN/SUBSTI}:查找var所表示的字符串中,行首被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;${var/%PATTERN/SUBSTI}:查找var所表示的字符串中,行尾被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;notice:PATTERN中使用glob风格和通配符;查找删除:${var/PATTERN/SUBSTI}:以PATTERN为模式查找var字符串中第一次的匹配,并删除之;${var//PATTERN}:以PATTERN为模式查找var字符串中的匹配,并全部删除;${var/#PATTERN}:以PATTERN为模式查找var字符串行首的匹配,并全部删除;${var/%PATTERN}:以PATTERN为模式查找var字符串中的匹配,并全部删除;${var/%PATERN}:以PATTERN为模式查找var字符串末尾的匹配,并删除之;字符串大小写转换:${var^^}:把var中的所有的小写字符转换为大写${var,,}:把var中的所有大写字符转换为小写;变量赋值:${var:-VALUE}:如果var变量为空,或未设置,那么返回value;否则,则返回var变量的值;${var:=VALUE}:如果var变量为空,或未设置,那么返回VALUE,并将VALUE赋值给var变量;否则,则返回var变量的值;${var:+VALUE}:如果var变量不空,则返回VALUE;${var:?ERRROR_INFO}:如果var为空,或未设置,那么返回ERROR_INFO为错误提示;否则,返回var值;练习:写一个脚本,完成如下功能(1)提示用户输入一个可执行命令的名称;(2)获取此命令所依赖的所有库文件列表;(3)复制命令至某目标目录(例如/mnt/sysroot,即把此目录当作根)下的对应的路径中bash,/bin/bash ==> /mnt/sysroot/bin/bashuseradd,/usr/sbin/useradd ==> /mnt/sysroot/lib64/ld-linux-x8664.so.2进一步:每次复制完成一个命令之后,不要退出,而是提示用户继续输入要复制的其它命令,并重复完成如上所描述的功能;知道用户输入"quit"脚本 bash特性:引用命令的执行结果:$(COMMAND) 或者 `` 反引号示例: mkdir $(date +%H-%M-%s)stat:查看文件或者文件系统的状态示例: stat /etc/fstabFile: ‘/etc/fstab’Size: 465 Blocks: 8 IO Block: 4096 regular fileDevice: fd00h/64768d Inode: 33554498 Links: 1Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)Access: 2018-11-28 18:16:42.497510412 +0800Modify: 2018-11-17 23:20:14.801999430 +0800Change: 2018-11-17 23:26:58.495992201 +0800Birth: -linux 文件包含2类属性:元数据: metadata数据:date正则匹配:[[:upper:]] 所有的大写字母匹配[[:lower:]] 所有的小写字母匹配[[:alpha:]] 所有字母匹配[[:digit:]] 所有数字匹配[[:alnum:]] 所有字母数字匹配[[:space:]] 所有空白字符匹配[[:punct:]] 所有标点符号匹配[^] 匹配直指定范围外的单个字符[^[:upper]] 匹配任意大写字母之外的单个字符[^0-9][^[:alnum:]] 匹配非数字字母之外的单个字符 IO重定向及管理程序:指令+数据程序:IO程序的数据流有三种:输入的数据流: <----- 标准输入(stdin), 键盘输出的数据流: -----> 标准输出(stdout), 显示器错误输出流: -----> 错误输出(stderr), 显示器fd: file descriptor 文件描述符标准输入 0标准输出 1错误输出 2输出重定向 >特性 覆盖输出>>特性 追加输出set -C 禁止覆盖输出重定向向至已存在的文件此时可使用强制覆盖输出 >|set +C关闭上述特性 这个效果仅对当前shell有效错误输出流重定向:2> , 2>>合并正常输出流和错误输出流 &> , &>>COMMAND > /PATH/TO/SOMEFILE 2>&1COMMAND >> /PATH/TO/SOMEFILE 2>&1----这个地方不太理解 要反复练习理解输入重定向 <tr命令tr [option] ... SET1 [SET2]把输入的数据当中的字符,凡是在set1定义范围内出现的,通通对位转换为set2出现的字符用法1: tr set1 set2 < /path/from/somefile用法2: tr -d set1 < /path/from/somefile以上2中操作都不修改源文件Here Document : <<cat << EOFcat > /path/to/somefile << EOF 这个知识点很重要 很多次都没有理解 管道:链接程序,实现将前一个命令的输出直接定向后一个程序当做输入数据流COMMAND1 | COMMAND2 | COMMAND3 | ... tee 命令:COMMAND | tee /PATH/TO/SOMEFILE 既可以输出查看的文件 又保存至其他位置#!/bin/bash#cat << EOF disk) show disks infomem) show memory infocpu) show cpu info*)QUITEOFread -p "Your choice: " optionif [[ "$option" == "disk" ]];thenfdisk -l /dev/[sh]d[a-z]elif [[ "$option" == "mem" ]];thenfree -melif [[ "$option" == "cpu" ]];thenlscpuelseecho "Unkown option"exit 3fi#!/bin/bash#for username in user21 user22 user23;douseradd $usernamedone#求100以内所有正整数之和#!/bin/bashdeclare -i sum=0for i in {1..100};doecho "\$sum is $sum , \$i is $i"sum=$[$sum+$1]doneawk命令:FS 默认的内置输入变量 默认为空白字符 如果在awk命令行重新定义 只需要-v 定义就可以了 示例:awk -v FS=':' '{print $1}' /etc/passwd 指的是以 : 为分隔符好进行打印awk -v FS=':' '{print "hello:",$1}' /etc/passwd上面的2条命令也可以通过-F:就可以是分隔符为:号进行打印的需求了awk -F: '{print "hello\ world:\ ",$1}' /etc/passwdOFS 内置的输出变量符 默认为空白字符 可以自定义FS OFS 区别主要是输入判断的变量符号 和输出表现的变量符号 比较容易理解示例awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwdRS: input record seperator 输入时的换行符ORS: output record seperator 输出时的换行符示例:awk -v RS=' ' -v ORS='#' '{print}' /etc/passwdawk -v RS=' ' -v ORS='#' '{print}' /var/log/messages解释:输入的时候以空格为换行符 然后输出的时候 有空格的时候就会转换为#号 这个地方不好理解NF: number of field 字段数量 记录每行以默认空格计算有多少字段示例:awk '{print NF}' /etc/log/messagesawk '{print NF}' /etc/passwd$NF: NF会得到每行以空格计算有多好字段 然后拿到这个字段数 然后打印这个字段的值取字段变量的最后一个值示例:awk '{print $NF}' /var/log/messages awk 内部引用变量不需要加$ 直接引用即可 NR: 记录文件的行数 后面跟多个文件的时候 继续增加行数 而是不区分文件进行计数示例:awk '{print NR}' /etc/passwdawk '{print NR}' /var/log/messages /etc/passwdawk -F: '(NR>=2&&NR<=10) {print $1}' /etc/passwdFNR: awk后面跟多个文件的时候 分别记录文件的行数 示例:awk '{print FNR}' /etc/fstab /etc/passwdFILENAME 显示文件名 一个文件要是有多少行 就会显示多少遍示例:awk '{print FILENAME}' /etc/fstab /etc/passwd 不建议常用 但是思想是可以遍历文件多少行 每行都会处理ARGC: 命令行参数的个数示例:awk '{print ARGC}' /etc/passwd /etc/issue /etc/fstab 记录命令行参数的个数 awk和自己的参数算只能算一个 文件有多少行就会显示多少遍awk 'BEGIN{print ARGC}' /etc/passwd /etc/fstab /etc/issue 在打印前面加BEGIN就会只显示一遍ARGV: 数组,保存的是命令行所给定的各参数示例:awk '{print ARGV[0]}' /etc/passwd /etc/fstab /etc/issue 只会打印awk这个下标的数组 不加BEGIN的时候文件有多少行就会显示多少遍awk 'BEGIN{print ARGV[0],ARGV[1],ARGV[2],ARGV[3]}' /etc/passwd /etc/fstab /etc/issue /var/log/messages 在前面print添加BEGIN之后就只显示一遍 根据下标打印相对应的数组值 2.2自定义变量-v var=value变量名区分大小写在program中直接定义示例:awk -v test="hello world" '{print test}' /etc/fstab awk -v test="hello world" 'BEGIN{print test}' /etc/fstabprint 打印变量的时候直接引用变量名 /etc/fstab 这个地方值利用的是行数 文件有多少行就会打印多少遍hello world 前面加BEGIN的时候只会打印一遍了awk '{test="hello world";print test}' 可以在print中直接定义变量awk 'BEGIN{test="hello world";print test}' /etc/fstab 2.3 printf 命令格式化输出: printf FORMAT,item1,item2,...FORMAT必须给出printf不会自动换行,需要显示给出换行控制符,\nFORMAT 中需要分别为后面的每个item指定一个格式化符号格式符:%c: 显示字符的ASCII码%d %i: 显示十进制整数 decimal intege 单词可能不太准确%e %E: 科学计数法数值显示%f: 显示为浮点数%g %G: 以科学计数法或浮点形式显示数值%s: 显示字符串%u: 无符号整数%%: 显示%自身示例:awk -F: '{printf "%s",$1}' /etc/passwd 把$1套到%s进行以字符串进行显示 默认不加换行符就会显示在一行中awk -F: '{printf "%s\n",$1}' /etc/passwd \n就会每一行只显示一个用户名awk -F: '{printf "Username: %s\n",$1}' /etc/passwd 还可以加前缀提示字符进行显示awk -F: '{printf "Username: %s,UID: %i\n",$1,$3}' /etc/passwdawk -F: '{printf "Username: %s,UID: %i\n",$1,$3}' /etc/passwd 第一个%s后面不能加\n不然每一行都会在2行进行显示了 在最后一个FORMAT定义的变量之后加\n符号 这个是显示 用户名和UID %d %i 都是以数值的方式显示用户的UID修饰符:#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;%3.1f 默认这样的使用 以f居多默认对齐方式为右对齐示例:awk -F: '{printf "Username: %15s,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 4.操作符算数操作符x+y, x-y, x*y, x/y, x^y[x的y次方], x%y[取模] -x+x:转换为数值 [把字符串转换为数值]字符串操作符:没有符号的操作符,表示字符串连接赋值操作符:=,+=,-=, *=, /=, %=, ^=++, --比较操作符:>, >=, <, <=, !=, ==模式匹配符:~:左侧的字符是否能匹配右侧的字符!~:左侧的字符不匹配右侧的字符逻辑操作符:&& 与|| 或! 非函数调用:定义函数 后面跟上()就可以了 ()里面可以加上调用的参数function_name(argu1,argu2,argu2,...)条件表达式:selector:条件挑选器?:表示为真执行 if-true-expression否则执行 if-false-expression示例:selector?if-true-expression:if-false-expressionawk -F: '{$3>1000?usertype="Common User":usertype="System or Systemuser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd解释:-F: 定义打印格式 $3>1000 判断第三个字段是否大于1000 然后定义条件表达式 格式上面有解释,以:为分隔符进行判断 第一个为真后面就会打印 第二个为假后面会打印 字段使用双引号进行包含 printf 开始匹配打印 "15%s:%-s\n" printf的打印格式 %s默认为右对齐 15表示15个空格 %-s表示左对齐 $1是取字段第一个值 usertype是调用定义的变量字符串进行打印 后面是需要的条件输入文件位置 5、PATTERN(1) empty:孔模式,匹配每一行(2) /regular expression/:仅处理能够被此处的模式匹配到的行(3) relational expression:关系表达式:结果有"真"有"假":结果为"真"才会被处理;真:结果为非0值,非空字符串(4) line ranges:行范围startline,endline: /pat1/,/pat2/注意:不支持直接给出数字的格式示例:awk '/^UUID/{print $1}' /etc/fstab 在这儿就能实现UUID匹配行的打印 打印第一个字段 默认的变量还是以空格为分割awk '!/^UUID/{print $1}' /etc/fstab 打印匹配模式以外的行 然后打印第一个字段awk -F: '$3>100{print $1,$3}' /etc/passwd $3>100是进行模式匹配 然后再后面打印 就可以实现类似grep的功能了awk -F: '$3>100{printf "%15s:%-s\n",$1,$3}' /etc/passwdawk -F: '$3<100{printf "%15s:%-s\n",$1,$3}' /etc/passwdawk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd 查找/etc/passwd中shell为/bin/bash的用户awk -F: '$NF~/bash$/{print $1,$NF}' /etc//passwd $NF模式匹配 ~进行模式匹配 匹配的内容要用//括起来 /bash$/以bash结尾的用户awk -F: '$NF!~/bash$/{print $1,$NF}' /etc//passwd 不以/bash$/结尾的在$NF后面加一个!就可以awk -F: '/^r/,/^s/{print $1}' /etc/passwd /pat1/,/pat2/ 模式匹配 从r字母开头的行匹配到s开头的行结束awk -F: 'BEGIN{print " username uid \n---------------"}{print $1,$3}' /etc/passwd BEGIN 和 END的使用方法awk '/^[[:space:]]*linux16/{print}' /etc/grub2.cfg 打印这个文件中以开头为空格的字符 然后后面匹配Linux16的行(5) BEGIN / END 模式BEGIN{}: 仅在开始处理文件中的文本之前执行一次;END{}:仅在文本处理完成之后执行一次;示例:awk -F: '{print " username uid \n---------------"}{print $1,$3}END{print "=====================\n end"}' /etc/passwd END用在最后进行使用 打印结尾 表示 6. 常用的action(1) Expressions(2) Control statements: if while等:(3) Compound statements:组合语句(4) input statements(5) output statements 7. 控制语句if(condition) {statements}if(condition) {statements} else {statements}while(condition) {statements}do {statements} while{condition}for(expr1;expr2;expr3) {statements}breakcontinuedelete array[index]delete arrayexit{statements}7.1 if-else语法:if(condition) {statements} else {statements} 使用场景:对awk取得的整行或某个字段做条件判断示例: awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwdawk -F: '{if($3>100) print $1,$3}' /etc/passwdawk -F: '{if($3>100) {printf "Common user: %s\n",$1} else {printf "root or Systemuser: %s\n",$1}}' /etc/passwdif-else的时候要把{prinf}都用大括号个括住了 不然会报语法错误awk '{if(NF>5) print $0}' /etc/fstab 对字段数大于5的进行printdf -Th | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>4) print $1}'7.2 while 循环示例:awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfgawk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) print $i,length($i);i++}}' /etc/grub2.cfg 嵌套if循环判断7.3 do-while循环语法:do statement while(condition)意义:至少执行一次循环体7.4 for循环语法: for(expr1;expr2;expr3) statementfor(variable assignment;condition;iteration process) {for-body}awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg特殊用法:能够遍历数组中的元素:语法:for(var in array) {for-body}7.5 switch语句语法: switch(expression) {case VALUE1 or /REGEXP1/: statement;case VALUE2 or /REGEXP2/: statement;...;default: statement}7.6 break和continuebreak [n] 退出n层循环continue7.7 next提前结束对本行的处理而直接进入下一行;示例:awk -F: '{if($3%2!=0) next; print $1,$3}' /etc//passwd 8.array关联数组:array[index-expression]index-expression (1)可使用任意字符串:字符串要使用双引号;(2)如果某数组元素事先不存在,在引用时,awk会自动创建,并将其初始化为"空串";若要判断数组中是否存在某元素,要使用"index in array" 格式进行weekdays[mon]="Monday"若要遍历数组中的每个元素,要使用for循环;for(var in array) {for-body}示例:awk 'BEGIN{weekdays["mon"]="moday";weekdays["tue"]="Tuesday"; for(i in weekdays) {print weekdays[i]}}'注意: var会遍历array的每个索引使用场景:统计打印结果中某个字符串出现的次数netstat -ntlp | awk '/^tcp\>/{state[$NF]++}END { for(i in state) {print i.state[i]}}'awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log 统计ip访问的次数 俗称报告生成器awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab 统计系统文件类型出现的次数awk '{for(i=1;i<NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab 统计文件单词出现的次数{for(i=1;i<NF;$i++){count[$i]++}} 使用for循环做定义判断 NF记录的是文件字段出现的次数 count[$i]++ 则是使用$i下标进行统计次数 每次+1 9.函数9.1内置函数函数处理;rand();返回0和1直接的随机数 awk在系统第一次打印时 是随机的而后的打印都是保持第一次的随机数字符串处理;length([s]): 返回指定字符串的长度sub(r,s,[t]): 以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容 这个只会替换第一次替换不会 全局进行替换gsub(r,s,[t]):表示全局进行替换示例:awk -F: '{print sub(o,O,$1)}' /etc/passwd 使用print的时候会打印结果1表示不成功 0表示成功split(s,a,[r]) : 以r为字符切割字符s,并将切割后的结果保存至a所表示的数组中示例:netstat -tan | awk '/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count) {print i,count[i]}}'详解: {split($5,ip,":")} 以第5个字段进行切割保存至ip数组中,":"以分隔符进行切割ip[1] 是以":"切割之后拿到左面第一个字段的值count[ip[1]]++ 拿到左面第一个字段下表的记录 每次都+1 做数组循环{split($5,ip,":");count[ip[1]]++}END最后只打印一次{for(i in count) {print i,count[i]}} 做数组循环判断进行打印结果

 

转载于:https://www.cnblogs.com/S--S/p/10177047.html

总结

以上是生活随笔为你收集整理的shell-awk详细笔记的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。