awk实现Left、join查询、去除重复值以及局部变量讲解例子

最近看到论坛里面有几个不错的小例子,对于学习awk还是有帮助,在这儿详细的说一下

一、类似数据库中的left join查询

代码如下:

[root@krlcgcms01 mytest]# cat a.txt    //a.txt
111   aaa
222   bbb
333   cccc
444   ddd
[root@krlcgcms01 mytest]# cat b.txt    //b.txt
111  123  456
2    abc  cbd
444  rts  786

要求输出结果是
111,aaa,123,456
444,ddd,rts,786

实现方法:

代码如下:

[root@krlcgcms01 mytest]# awk 'NR==FNR{a[$1]=$2;}NR!=FNR && a[$1]{print $1","a[$1]","$2","$3}' a.txt b.txt
111,aaa,123,456
444,ddd,rts,786

解释:当NR和FNR相同时,这就说明在对第一个文件进行操作,a[$1]=$2表示,建立一个数组,以第一个字段为下标,第二个字段为值。当NR!=FNR时,说明在对第二个文件进行操作,注意:这个时候的$1和前面的$1不是同一个东西了,前面的$1表示的是a.txt的第一个字段,而后面的$1表示的是b.txt的第一个字段。a[$1]表示以b.txt中第一个字段的为下标的值,如果a[$1]有值的话,说明也存在于a.txt文件中,这样就把数据print出来就行了。

实现方法2:


代码如下:

[root@krlcgcms01 mytest]# awk -v OFS="," 'NR==FNR{a[$1]=$2;} NR!=FNR && $1 in a { print $1,a[$1],$2,$3}' a.txt b.txt
111,aaa,123,456
444,ddd,rts,786

解释:-v OFS=","这个是设置输出时的列分割符,$1 in a这个是b.txt文件中的第一列的值是不是在数组a的key中,这个对做程序的来说很好理解,各种语言当中都有这样的用法,或者函数。例如,php中有in_array函数。比较一下,方法1和方法2中的print,方法1我加了双引号,方法2我却没有加,但是输出的效果却是一样的。

二、去除重复的值

代码如下:

[root@krlcgcms01 mytest]# cat repea   //文件repea
 a b
 c d
 e f
 b d
 b a
 f e
 1 2
 2 1

如果有a,b和b,a这样的情况,就删除b,a,当然数字也一样;

实现方法1:


代码如下:

awk '{for(i=1;i<=NF;i++)a[i]=$i;asort(a);for(i=1;i<=length(a);i++)printf a[i]"\t";printf "\n"}' repea|sort|uniq
1       2
a       b
b       d
c       d
e       f

解释:for(i=1;i<=NF;i++)a[i]=$i;将每一列中的二个字段放到数组中,asort(a),这个数组进行排序,后面的代码是将数组数据输出来,通sort命令对输入的数据进行排序,相同数据会排在一起,通过uniq来进行去除相同的列。这种方法比较有通用性,不光适合二列,三列,四列都行。不过效率差了点。

实现方法2:


代码如下:

[root@krlcgcms01 mytest]# awk '{a[$0]=$0;if (!($2 OFS $1 in a)) print a[$0] }' repea
a b
c d
e f
b d
1 2
[root@krlcgcms01 mytest]# awk '{a[$0];if (!($2 OFS $1 in a)) print  }' repea   
a b
c d
e f
b d
1 2

解释:方法2的二种写法,出来的结果是一样的,a[$0];没有赋值也没有报错,为什么呢?awk在遇到这样没有定义的变量时,会给它一个初值。if (!($2 OFS $1 in a))表示返转字段不在数组a中,这里所说的在,表示key是不是存在,不是值。print 不写默认是一行。

实现方法3:


代码如下:

[root@krlcgcms01 mytest]# awk '!a[$1_$2]++&&!a[$2_$1]++' repea
a b
c d
e f
b d
1 2
[root@krlcgcms01 mytest]# awk '{if(!a[$1_$2]++&&!a[$2_$1]++)print $0;}' repea
a b
c d
e f
b d
1 2

解释:!a[$1_$2]++&&!a[$2_$1]++等于if(!a[$1_$2]++&&!a[$2_$1]++),对于首次出现的记录,a[$2_$1]的值是未定义的,由于后面的 ++ 是数学计算,所以a[$2_$1]会被赋值成数字0,也是由于 ++ 操作符,会先取值,再计算,从左到右 ++ 运算符的优先级大于!运算符的,所以对于第一行记录实际上是if(! 0) print $0     ! 是取反,0 是假,! 0 就是真,那么就会执行后面的 print $0对于后面出现的重复记录,a[$0] 经过 ++ 的计算已经变为 1、2、3 。。。而 ! 1  ! 2  ! 3 ... 都为假,不会打印。

三、awk的局部变量

这个例子来说明一下,awk怪异的局部变量

代码如下:

[root@krlcgcms01 mytest]# cat sum 
 1       2 
 2       3 
 a       b 
 3       2 
 4       1 
 3       r

把都是数字的行,最大的那个数字加起来,第一行是2,第二行是3,每四行是3,第五行是4,总和是12

代码如下:

function max(one,two){
 if(one > two){
 sum = sum + one;
 }else{
 sum  = sum + two;
 }
 }

{if($1~"[0-9]" && $2~"[0-9]") max($1,$2);}
 END{print "sum="sum}

在max方法里面,变量sum是会影响外面的,这里的sum是全局的。
[root@krlcgcms01 mytest]# awk -f add.sh sum
sum=12

代码如下:

function max(one,two,sum){    //方法中的sum局部变量
if(one > two){
sum = sum + one;
}else{
sum  = sum + two;
}
}

{if($1~"[0-9]" && $2~"[0-9]") max($1,$2,sum);}

END{print "sum="sum}         //所以为空

[root@krlcgcms01 mytest]# awk -f add.sh sum
sum=

代码如下:

function max(one,two,sum){
 if(one > two){
 sum = sum + one;
 }else{
 sum  = sum + two;

}

return  sum                 //加上return就可以了
 }

{if($1~"[0-9]" && $2~"[0-9]") sum = max($1,$2,sum);}

END{print "sum="sum}

(0)

相关推荐

  • awk实现Left、join查询、去除重复值以及局部变量讲解例子

    最近看到论坛里面有几个不错的小例子,对于学习awk还是有帮助,在这儿详细的说一下 一.类似数据库中的left join查询 复制代码 代码如下: [root@krlcgcms01 mytest]# cat a.txt    //a.txt 111   aaa 222   bbb 333   cccc 444   ddd [root@krlcgcms01 mytest]# cat b.txt    //b.txt 111  123  456 2    abc  cbd 444  rts  786

  • mysql实现合并结果集并去除重复值

    目录 mysql 合并结果集并去除重复值 mysql 合并结果集(union,union all) union 与 union all 执行结果不同 对UNION,UNION ALL的结果继续处理,需要加括号 mysql中,UNION,UNION ALL的性能/效率不同 总结 mysql 合并结果集并去除重复值 SELECT DISTINCT c.parent_id from (     SELECT parent_id  FROM tp_goods_category a join tp_goo

  • 字符串聚合函数(去除重复值)

    --功能:提供字符串的替代聚合函数 --说明:例如,将下列数据 --test_id test_value -------------------- 'a' '01,03,04' 'a' '02,04' 'b' '03,04,08' 'b' '06,08,09' 'c' '09' 'c' '10' --转换成test_vlaue列聚合后的函数,且聚合后的字符串中的值不重复 --test_id test_value -------------------- 'a' '01,03,04,02' 'b'

  • hashset去除重复值原理实例解析

    Java中的set是一个不包含重复元素的集合,确切地说,是不包含e1.equals(e2)的元素对.Set中允许添加null.Set不能保证集合里元素的顺序. 在往set中添加元素时,如果指定元素不存在,则添加成功.也就是说,如果set中不存在(e==null?e1==null:e.queals(e1))的元素e1,则e1能添加到set中. 下面以set的一个实现类HashSet为例,简单介绍一下set不重复实现的原理: package com.darren.test.overide; publ

  • js数组中去除重复值的几种方法

    在日常开发中,我们可能会遇到将一个数组中里面的重复值去除,那么,我就将我自己所学习到的几种方法分享出来 去除数组重复值方法: 1,利用indexOf()方法去除 思路:创建一个新数组,然后循环要去重的数组,然后用新数组去找要去重数组的值,如果找不到则使用.push添加到新数组,最后把新数组返回回去就行了 看不懂没关系,上代码就比较容易懂了 function fun(arr){ let newsArr = []; for (let i = 0; i < arr.length; i++) { if(

  • pandas去除重复值的实战

    目录 加载数据 sample抽样函数 指定需要更新的值 append直接添加 append函数用法 根据某一列key值进行去重(key唯一) 加载数据 首先,我们需要加载到所需要的数据,这里我们所需要的数据是同过sample函数采样过来的. import pandas as pd #这里说明一下,clean_beer.csv数据有两千多行数据 #所以从其中采样一部分,来进行演示,当然可以简单实用data.head()也可以做练习 data = pd.read_csv('clean_beer.cs

  • 详解JavaScript数组和字符串中去除重复值的方法

    原理在代码中表现得非常清晰,我们直接来看代码例子: var ages = array.map(function(obj) { return obj.age; }); ages = ages.filter(function(v,i) { return ages.indexOf(v) == i; }); console.log(ages); //=> [17, 35] function isBigEnough(element) { return element >= 10; } var filte

  • 解析mysql中:单表distinct、多表group by查询去除重复记录

    单表的唯一查询用:distinct多表的唯一查询用:group bydistinct 查询多表时,left join 还有效,全连接无效,在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重复记录的所有值.其原因是distinct只能返回它的目标字段,而无法返回其它字段,用distinct不能解决的话,我只有用二重循环查询来解决,而这样对于一个数据量非常大的

  • js数组中删除重复值的代码小结

    js数组中去除重复值 Array.prototype.del = function() { var a = {}, c = [], l = this.length; for (var i = 0; i [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 方法二 复制代码 代码如下: //去重复数组 function unique(data){ data = data || []; var a = {}; len = data.length; for (var i=0; i<len;i++

  • JS实现的数组去除重复数据算法小结

    本文实例讲述了JS实现的数组去除重复数据算法.分享给大家供大家参考,具体如下: 在JS中经常会遇到去除数组中重复数据的需求,在此介绍四种算法以实现JS数组去重的功能. 1. 速度最快算法:对象键值对法 实现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键,不是的话给对象新增该键并放入新数组. //注意点: 判断 是否为js对象键时,会自动对传入的键执行"toString()",不同的键可能会被误认为一样:例如: a[1].a["1"] .解决

随机推荐