shell命令技巧——文本去重并保持原有顺序

简单来说,这个技巧对应的是如下一种场景

假设有文本如下

cccc
aaaa
bbbb
dddd
bbbb
cccc
aaaa

现在需要对它进行去重处理,这个很简单,sort -u就可以搞定,但是如果我希望保持文本原有的顺序,比如这里有两个aaaa,我只是希望去掉第二个aaaa,而第一个aaaabbbb的前面,去重后仍旧要在它前面,所以我期望的输出结果是

cccc
aaaa
bbbb
dddd

当然,这个问题本身并不难,用C++或python写起来都很容易,但所谓杀机焉用牛刀,能用shell命令解决时,它永远都是我们的首选。答案在最后给出,下面说说我是如何想到这样

我们有时候想把自己的目录加入环境变量PATH时会在~/.bashrc文件中这样写,比如待加入的目录为$HOME/bin

export PATH=$HOME/bin:$PATH

这样我们等于是在PATH追加了路径HOME/bin并让它在最前面被搜索到,但当我们执行‘source /.bashrc‘后,HOME/bin目录就会被加入PATH,如果我们下次再添加一个目录,比如

export PATH=$HOME/local/bin:$HOME/bin:$PATH

再执行source ~/.bashrc时,$HOME/bin目录在PATH中其实会有两份记录,虽然这不影响使用,但对于一个强迫症来说,这是无法忍受的,于是问题就变成了,我们需要去掉$PATH里重复的路径,并且保持原有路径顺序不变,也就是原本谁在前面,去重后仍旧在前面,因为在执行shell命令时是从第一个路径开始查找的,所以顺序很重要

好了,说了这么多我们来揭示最终的结果,以文章开始的数据为例,假设输入文件是in.txt,命令如下

cat -n in.txt | sort -k2,2 -k1,1n | uniq -f1 | sort -k1,1n | cut -f2-

这些都是很简单的shell命令,下面稍作解释

cat -n in.txt : 输出文本,并在前面加上行号,以\t分隔
sort -k2,2 -k1,1n : 对输入内容排序,primary key是第二个字段,second key是第一个字段并且按数字大小排序
uniq -f1 : 忽略第一列,对文本进行去重,但输出时会包含第一列
sort -k1,1n : 对输入内容排序,key是第一个字段并按数字大小排序
cut -f2- : 输出第2列及之后的内容,默认分隔符为\t

大家可以从第一条命令开始,并依次组合,看看实际输出效果,那样便更容易理解了。对于$PATH中的重复路径又该如何处理呢,还是以前面的例子来说,只需在前后用tr做一下转换即可

export PATH=$HOME/local/bin:$HOME/bin:$PATH
export PATH=`echo $PATH | tr ‘:‘ ‘\n‘ | cat -n | sort -k2,2 -k1,1n | uniq -f1 | sort -k1,1n | cut -f2- | tr ‘\n‘ ‘:‘`

其实这样使用PATH会有个问题,比如我们执行了以上命令后,如果想去掉$HOME/bin这个路径,仅仅修改为如下内容是不够的

export PATH=$HOME/local/bin:$PATH
export PATH=`echo $PATH | tr ‘:‘ ‘\n‘ | cat -n | sort -k2,2 -k1,1n | uniq -f1 | sort -k1,1n | cut -f2- | tr ‘\n‘ ‘:‘`

因为我们已经将$HOME/bin加入了$PATH中,这样做并没有起到删除的作用,也许最好的方式还是自己清楚的知道所有路径,然后显示指定,而不是采取追加的方式

时间: 2024-08-06 15:58:06

shell命令技巧——文本去重并保持原有顺序的相关文章

日志处理中一些shell命令技巧

日志处理中一些shell命令技巧 阴差阳错的做的日志分析,前途未卜的这段日子,唯一还有点意思的可能就是手动的处理大量日志.总结一下. 日志文件的输入是动则几个G的文本.从N个这样的文件中得到一个列表,一个数字,一个比例.在什么工具都没有情况下,用shell命令不仅是验证系统数据的准确性的方法,也是一个很好的学习过程. 使用cut命令切割日志行 下面的一行典型的apache访问日志: 120.51.133.125 - - [26/Apr/2013:12:20:06 +0800] "GET /ski

vim 执行shell命令技巧

:!cmd不退出vim 执行命令 cmd:r !cmd不退出vim执行命令cmd,并将cmd的输出内容插入当前文本中.:shell切换到shell里(此时并没有退出vim,可以理解成vim转入后台),你可以在shell中做任何操作,退出shell(比如用exit)后,会切换回原来的vim中vim 执行shell命令技巧,布布扣,bubuko.com

shell 命令合并文本

之前想把代码打印出来看来着,后来合并完之后放在word里发现有2000多页,然后放弃了~anyway,这个命令还是挺有用的. 比如我有文本a001.dat, a002.dat, a003.dat ...,然后想合并成一个文本.直接在shell里敲下面这条(linux系统或者win下安装了cygwin): awk 1 a*.dat > a.dat awk是文本处理工具:1代表true,一直执行下去:*是通配符,代表任意字符.

linux命令 sort文本去重

对于sort 可以输出 不重复的字段的用法 sort -u <taskfile> 扩展 命令 sortx.sh #!/bin/bash /bin/sort -u $1 -o $1 此命令扩展 的意图 去除指定的文件中重复的单字 并写回原文件 这个命令对于基于文本处理并作模型构建的同学有方便之处 不必要自己写去重工具了

Shell命令之文本操作

前言 在Linux中,文本处理操作是最常见的,应用非常广泛,如果能熟练掌握,可以大大提高开发效率. awk/sed/grep是文本操作领域的“三剑客”,学会了这3个命令就可以应对绝大多数文本处理场景.这里,不对这三个命令进行过多的冗余描述,只是记录最常见的几种用法,起个抛砖引玉的作用.详细的文档还请参考官方文档. grep grep命令最常用,非常适合查找和匹配.结合管道运算符,可以达到非常好的效果. 常用场景: cat a.txt |grep -i "target" -i : 忽略大

Matlab使用新发现1(小技巧:shell 命令、工程工作目录设置相关)

最近在调试一个基于Matlab的程序,在偶然间发现了几个比较有趣的技巧,给大家分享一下(很可能是太菜鸟了,没有涉及这方面,大方之家请勿见笑,对您有所帮助请点赞!) 1. Matlab语言是一种解释型语言(interpreter) 就像我在总结软件架构数据流时的一种:Interpreter / virtual machine (解释器/虚拟机),具体架构可以参看以下博文:http://blog.csdn.net/lg1259156776/article/details/46802107(解释性语言

Linux常用命令(第二版) --Shell应用技巧

Shell应用技巧 小技巧: 1.命令补全功能: <Tab>键 2.清屏: Ctrl+l 3.删除光标前所有内容: Ctrl+u 4.命令历史记录: history 这时:  !history所列出的命令标号,就可以执行那条命令. 如: !188 而且: 按方向键↑和↓可查找以前执行过的命令. 重要技巧: 1.命令别名: 作用: 可以使操作更加容易,命令能够更加容易记忆. alias: 显示系统已经定义了的别名. 定义别名: alias copy=cp alias drm="rm -

Bash shell命令记录和CentOS的一些技巧

①CentOS的实用技巧: 一.按下ctrl+alt+F2可由图形界面切换至命令行(shell窗口),按下ctrl+alt+F1可由命令行切换至图形界面(前提是安装CentOS时软件选择项选择安装了图形界面,一般是GNOME) ②shell命令记录: 一.ifconfig命令是Linux中用于显示或配置网络设备的命令,英文全称是network interfaces configuring.配置网卡的IP地址语法例:ifconfig eth0 192.168.0.1 netmask 255.255

Linux Shell常用技巧(三) sed

Linux Shell常用技巧(三) sed 八.流编辑器sed 8.1 sed简介 sed是stream editor的缩写,一种流编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间"(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕.接着处理下一行,这样不断重复,直到文件末尾.文件内容并没有 改变,除非你使用重定向存储输出.sed主要用来自动编辑一个或多个文件,简化对文件的反复操作,编写转换程序等