终于明白awk如何牛掰地不排序也能去掉文件里的重复行了

因为工作原因,经常经统计一些文本内容,要去除重复,之前都是cat xx | sort | uniq 类的命令。

自从开始关注使用VIM之后,发现VIM真的很强大,直接有去重功能,怪不得这么多Linuxer都喜欢它。

我这里只说它的去重功能首先讲点基础,

awk流程是逐行处理的,默认从文件的第一行一直处理到文件最后一行,

还要知道awk的基本命令格式是'pattern{action}'先匹配各种各样的样式,然后大括号里处理如何打印输出,

默认的只要匹配了pattern就{print $0},如果pattern未命中其判断值为假(0)那么就不会再去处理{action}了

pattern命中则为判断值为真(非0)就去处理{action}。

以下操作都是在vim命令模式下的操作

复制内容到剪贴板

代码:

: sort //可以直接排序,这个太好用了

:g/^\(.*\)$\n\1$/d    //去除重复行

:g/\%(^\1$\n\)\@<=\(.*\)$/d //功能同上,也是去除重复行

:g/\%(^\1\>.*$\n\)\@<=\(\k\+\).*$/d//功能同上,也是去除重复行

其实都是一些正则,但是本人正则不太好,也真的解释不清,希望有大牛能详细的解释下,每个正则是神马意思!


因为工作原因,经常经统计一些文本内容,要去除重复,之前都是cat xx | sort | uniq 类的命令,自从开始关注使用VIM之后,发现VIM真的很强大,直接有去重功能,怪不得这么多Linuxer都喜欢它。我这里只说它的去重功能

以下操作都是在命令模式下的操作

复制内容到剪贴板

代码:

: sort //可以直接排序,这个太好用了

:g/^\(.*\)$\n\1$/d    //去除重复行

:g/\%(^\1$\n\)\@<=\(.*\)$/d //功能同上,也是去除重复行

:g/\%(^\1\>.*$\n\)\@<=\(\k\+\).*$/d//功能同上,也是去除重复行

其实都是一些正则,但是本人正则不太好,也真的解释不清,希望有大牛能详细的解释下,每个正则是神马意思!

-------------------------------------------------------------------------------------

awk '!a[$0]++'

而如果使用sort加uniq进行排序的话,这个文档是看不出有什么不妥。

不过我要处理的是用户名与密码一行行对应好的,如果使用sort + uniq处理的话,用户名都排到一块了,密码也又都跑到一块了。

这样就分不出来那个是那个了。

而使用的脚本很简单:

awk '!x[$0]++' filename

注:此处的x只是一个数据参数的名字而已,随你用a、b、c、d都行。

简要解释一下,awk 的基本执行流程是,对文件的每一行,做一个指定的逻辑判断,如果逻辑判断成立,则执行指定的命令;如果逻辑判断不成立,则直接跳过这一行。

我们这里写的 awk 命令是!x[$0]++,意思是:

首先创建一个 map 叫x,然后用当前行的全文$0作为 map 的 key,到 map 中查找相应的 value,如果没找到,则整个表达式的值为真,可以执行之后的语句;

如果找到了,则表达式的值为假,跳过这一行。

由于表达式之后有++,因此如果某个 key 找不到对应的 value,该++操作会先把对应的 value 设成 0,然后再自增成 1,这样下次再遇到重复的行的时候,对应的 key 就能找到一个非 0 的 value 了。

注:该处的map类似于array数组,只不过在awk中叫array不恰当。

awk Oneline中我们也学到过,awk 的流程是先判断表达式,表达式为真的时候就执行语句,可是我们前面写的这个 awk 命令里只有表达式,没有语句,那我们执行什么呢?原来,当语句被省略的时候,awk 就执行默认的语句,即打印整个完整的当前行。就这样,我们通过这个非常简短的 awk 命令实现了去除重复行并保留原有文件顺序的功能。

-------------------------------------------------------------------------------------

awk '!x[$0]++' shareprofile.txt > shareprofile_awk.txt

-------------------------------------------------------------------------------------

举个最简单的例子:awk '1' file和awk '{print $0}' file是一个道理,都是从头到尾依次打印文件的每一行

基础知识就这些,如果底太潮去man awk或者google找吧。

'!a[$0]++'

分成几个部分简单解释下吧

这个命令没有{action}也就是说,只要pattern部分判断值为真(非0)就打印正行,否则就跳过不打印

!在awk是取相反的意思,就是把对的变成错的把真的变成假的,放在这个命令中是神马作用一会解释

a[$0]这个非常好理解,建立数组a其变量是文本中的每一行,awk里$1是第一列,$2是第二列,以此类推$NF是最后一列,而$0是代表所有列及分隔符,也就是一整行,这样如果pattern是真的那就打印一整行

++的意思是a数组取变量完毕后,对该数组值+1

找个最简单的文档来解释一下

复制内容到剪贴板

代码:

cat file

xxx

yyy

xxx

zzz

这个文件有4行,其中第一、三行是重复的。套用这个命令处理流程如下

获取第一行a[xxx],因为这是第一行,数组a里从没见过xxx这个变量,那么自然他的值就是假(0)也就是说a[xxx]=0,这个时候!就有大作用了,他把a[xxx]假(0)变成了a[xxx]为真(!0)这个时候原本不改打印的第一行就变成了应该打印了,取逻辑反后对a[xxx]的值+1然后处理第二行

第二行a[yyy]这个情况跟刚才第一行的a[xxx]一样,也应该打印他

到第三行的时候情况遍了,因为第一行已经出现过了a[xxx]并且已经++过了他的值已经是非0而不是前两行的0了,本应打印但这时候再由!取逻辑反就不必打印了

第四行a[zzz]就又和第一、二两行一样了。

所以执行完就是这个结果

awk '!a[$0]++' file

xxx

yyy

zzz

再把file搞稍微复杂点

复制内容到剪贴板

代码:

awk '{print NR,$0}' file

1 xxx

2 yyy

3 zzz

4 xxx

5 yyy

6 zzz

7 xxx

8 yyy

9 zzz

一共9行文本,3行一次重复。为了看得更清楚,本来默认的{print $0}稍微改下,变成{print NR(行号),$0}。

那么现在来执行下刚才讲的试试看

复制内容到剪贴板

代码:

awk '!a[$0]++{print NR,$0}' file

1 xxx

2 yyy

3 zzz

复制内容到剪贴板

代码:

awk 'a[$0]++{print NR,$0}' file

4 xxx

5 yyy

6 zzz

7 xxx

8 yyy

9 zzz

很明显了吧,有!的命令是只打印第一次出现的$0也就是去除重复咯,而没有!的命令正好跟他相反,就是仅仅去除第一次出现的$0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,069评论 4 358
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,212评论 1 287
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 105,912评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,424评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,741评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,194评论 1 206
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,553评论 2 307
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,289评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,923评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,251评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,775评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,144评论 2 249
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,698评论 3 228
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,936评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,658评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,214评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,159评论 2 258

推荐阅读更多精彩内容

  • awk介绍awk变量printf命令:实现格式化输出操作符awk patternawk actionawk数组aw...
    哈喽别样阅读 1,486评论 0 4
  • Linux指令中文说明传送入口 整理自Linux指令中文说明 文本和数据进行处理的编程语言awk 是一种编程语言,...
    释闲人阅读 2,033评论 1 6
  • 本章主要学习内容awk介绍 awk基本用法 awk变量 awk格式化 awk操作符 awk条件判断 a...
    楠人帮阅读 1,214评论 0 8
  • 1、Nginx日志分析日志格式:'$remote_addr - $remote_user [$time_local...
    运维前线阅读 665评论 0 4
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 8,891评论 0 13