目录:
(九) 两个文件合并
(十) 关于 NFS 权限的设置
(十一) 求交集
(十二) 统计字符出现的次数
(十三) 求和
(十四) 案例实战
(九) 两个文件合并
(9.1) 首先我们在系统中定义两个文件 a1 和 a2, 现在我们的需求是使用 a1 的第二个字段去比对 a2 的第二个字段, 如果相同, 则将 a1 的第一个字段添加到 a2 文件的第三个字段上, 最终以 a2 文件为模板打印出对应的信息, 如果多个文件进行合并可以考虑使用数组
# awk -F"[ ,]" 'NR==FNR{a[$2]=$1}NR!=FNR{print $0,a[$2]}' a1 a2
(9.2) 我们创建两个文件 b1 和 b2, 现在我们希望将两个文件合并为如下的格式, 我们发现 b1 的第二列和 b2 的第一列是共同项, 然后我们在当 NR 不等于 FNR 的时候, 会进行打印的操作, 记得在字段之间使用 ":" 冒号进行分隔.
我们希望打印的结果如下:
- tom:001:aa
- tom:001:bb
- bob:002:cc
- bob:002:dd
- # awk -F: 'NR==FNR{a[$2]=$0}NR!=FNR{print a[$1]":"$2}' b1 b2
(9.3) 我们创建一个 c1 和 c2 文件, 如果 c1 的 $1 和 c2 的 $3 相同, c1 的 $2 和 c2 的 $4 的后三个字符相同, c1 的 $3 和 c2 的 $6 相同, 那么打印 c2 中符合条件的行, 如果需求是筛选多个共同列, 我们只要把这多个共同列进行合并比较即可. 我们发现 c1 中的第 1 列加第 2 列加第 3 列与 c2 文件中的第 3 列加第 4 列后三个字符加第 6 列, 如果是相同的, 那么就符合需求, 可以将 c2 文件中的当前行打印出来.
# awk 'NR==FNR{a[$1]=$1$2$3}NR!=FNR{X=substr($4,3);Y=$3X$6;if(Y==a[$3]){print}}' c1 c2
(9.4) 我们创建一个文件 d1 和 d2, 此时我们希望将 d2 文件中的第 2 个字段替换到 d1 文件的第 2 个字段, 首先要注意在使用文件名时要先用 d2 然后使用 d1, 同时指定输入和输出的分隔符都为 ":" 冒号, 然后执行将 d2 文件中的第 2 个字段替换到 d1 文件的第 2 个字段的操作.
# awk -F: 'BEGIN{FS=OFS=":"}NR==FNR{a[$1]=$2}NR!=FNR{$2=a[$1];print}' d2 d1
(十) 相同行合并为一行
(10.1) 我们创建一个文本文件 aa1, 现在我们的需求是将一个文件中将拥有相同字段的行合并成一行, 例如第一行第 1 个字段是 27, 第二行第 1 个字段也是 27, 则将第二行第 2 个字段的信息直接打印在第一行第 3 个字段的位置, 第三行第 1 个字段是 26, 所以直接打印到下一行, 以此类推. 首先使用 NR 是否等于 1 来进行判断, 如果 NR 为 1 则打印当前行并将第一行第 1 个字段赋值给变量 x, 接着是第二行, 发现 NR 不等于 1 了, 但是第二行第 1 个字段等于变量 x 的值, 所以此时用 printf 打印此 "%s" 格式, 然后处理第三行, 我们发现符合 "else if($1!=x)" 这个条件, 所以此时我们会先打印一个换行符 "\n" 然后再打印这一整行的内容, 并将当前行的第 1 个字段赋值给变量 x, 这样我们就基本可以实现我们所需求的格式了.
# awk 'NR==1{printf"%s", $0;x=$1}NR!=1{if($1==x){printf" %s", $2}else if($1!=x){printf"\n%s", $0;x=$1}}END{printf"\n"}' aa1
(十一) 求交集
(11.1) 现在我们创建了两个文件 a1 和 a2, 现在要求打印 a1 文件中的一些行, a1 的第 2 字段出现在 a2 的第 1 个字段中, 现在如果要求 a 的某部分是否出现在 b 的某部分里的时候, 那么我们就把 b 的那部分设置为数组的下标, 然后判断 a 的那部分是否是下标的一个元素. 此时则应该为 "awk -F"[,/]"'' a2 a1"# awk -F"[,/]"'NR==FNR{a[$1]=$0}NR!=FNR{if($2 in a){print $0}}' a2 a1
(11.2) 现在我们创建两个文件 b1 和 b2, 现在我们的需求是打印 b1 的一些行, b1 的 $1 出现在 b2 的第 1 个字段里, 找到那些行之后, 并把 b2 里对应的这些行的 $2 部分进行求和, 我们可以先在 b2 文件中将所有的第 1 字段的第 2 个字段值进行相加操作, 最后在 b1 文件行打印出来时也把相加的值一同打印出来.
# awk -F, 'NR==FNR{a[$1]+=$2}NR!=FNR{if($1 in a){printf"%s,%f\n",$0,a[$1]}}' b2 b1
(十二) 统计字符出现的次数
(12.1) 我们有一个文件 a1, 现在我们需要统计每个字符在文本文件中出现的次数, 此时我们的思路是遇到一个字段就将其设置为一个元素的下标, 当我们已经定义了一个元素时, 如果下次再遇到这个下标的元素的时候, 则加上 1 次. 我们首先是使用循环遍历每一行, 使用遍历的字段作为数组的下标, 如果后面出现了相同的字段, 则将统计的结果加 1, 然后在 END 中去遍历数组中每个元素当前的数值, 此时就可以得到每个字符在文本文件中出现的次数.
# awk '{for(i=1;i<=NF;i++){a[$i]++}}END{for(x in a){print x" 一共出现了 "a[x]" 次 "}}' a1
(十三) 求和
(13.1) 在我们的内存中正常是会将内存的数据写入到硬盘中的, 因此内存的数据和硬盘的数据是同步的, 我们称之为干净数据, 但是有时候在我们的内存中有些数据修改完后并没有写入到硬盘中去, 内存中的数据和硬盘数据并不同步, 此时这类数据我们称之为脏数据, 如果脏数据没有及时写入到硬盘, 那么当计算机重启之后没有写入到硬盘的数据就会丢失了. 现在我们的需求是计算出某个进程一共有多少个干净页, 有多少个脏页, 我们是可以从 / proc/1/smaps 的系统映射文件中查看到我们所需的内存相关信息的, 我们可以使用模式匹配的方式, 将干净页和脏页分别进行统计, 在之前的基础上进行连加操作.
- # cat /proc/1/smaps
- # cat /proc/1/smaps | awk '/Shared_Clean/{AA+=$2}/Shared_Dirty/{BB+=$2}END{print" 干净页总合是 "AA"KB";print" 脏页的总合是 "BB"KB"}'
(13.2) 现在我们有两个文件 a1 和 a2, 因为我们发现 a1 文件和 a2 文件的列数是一样的, 所以现在我们的需求是希望将 a1 文件和 a2 文件中对应的列数进行相加得到一个相加后的一行数组. 解决这个问题的思路我们是把一个文件里所有的数字放在一个数组里保存, 然后读取第二个文件, 把第二个文件里所有的数组保存, 然后分别相加 (图 13-5). 当然我们也可以使用 getline 函数解决问题, 首先使用 for 循环获取 a1 文件的所有值, 然后使用 getline 读取 a2 文件读取的行替换到当前所在行的信息, 最后使用 for 循环去遍历数组 a 与当前 a2 文件中的每个字段, 并进行相加的操作, 此时也可以得到我们所需的结果 (图).
- # awk 'NR==FNR{for(i=1;i<=NF;i++){a[i]=$i}}NR!=FNR{for(i=1;i<=NF;i++){b[i]=$i;printf"%s ",a[i]+b[i]}}END{printf"\n"}' a1 a2
- # awk '{for(i=1;i<=NF;i++){a[i]=$i};getline <"a2";for(i=1;i<=NF;i++){printf"%s ",a[i]+$i}printf"\n"}' a1
(十四) 案例实战
(14.1) 取得网卡的 IP
# ifconfig | grep 'inet' | grep broadcast | awk '{print $2}'
(14.2) 取得系统内存大小
# cat /proc/meminfo | awk '/MemTotal/{print $2}'
(14.3) 修改 CSV 文件各字段的顺序, 我们先在系统中创建一个 data.CSV 的文件, 想要把第 2 个字段和第 4 个字段进行调换.
# cat data.CSV | awk -F, 'BEGIN{OFS=","} {print $1,$4,$3,$2,$5,$6,$7}'
来源: http://www.bubuko.com/infodetail-3345371.html