有没有办法删除在Unix系统中的文件重复行?
我可以做到这一点sort -u
和uniq
命令,但我想用sed
或awk
。 那可能吗?
有没有办法删除在Unix系统中的文件重复行?
我可以做到这一点sort -u
和uniq
命令,但我想用sed
或awk
。 那可能吗?
awk '!seen[$0]++' file.txt
seen
是一个关联-数组awk将通过该文件的每一行。 如果行不是阵列中然后seen[$0]
将评估为假。 该!
是逻辑NOT运算符和将反转假为真。 awk将打印在表达式的值为真行。 所述++
增量seen
,使得seen[$0] == 1
在第一时间之后的线被发现,然后seen[$0] == 2
,依此类推。
AWK评估一切,但0
和""
(空字符串)为true。 如果重复线路被放置在seen
那么!seen[$0]
会评估为false,该线路将不会被写入到输出。
从http://sed.sourceforge.net/sed1line.txt :(请不要问我这是如何工作;-))
# delete duplicate, consecutive lines from a file (emulates "uniq").
# First line in a set of duplicate lines is kept, rest are deleted.
sed '$!N; /^\(.*\)\n\1$/!P; D'
# delete duplicate, nonconsecutive lines from a file. Beware not to
# overflow the buffer size of the hold space, or else use GNU sed.
sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'
Perl的一个班轮类似@乔纳斯的awk的解决方案:
perl -ne 'print if ! $x{$_}++' file
这种变化比较删除之前结尾的空白:
perl -lne 's/\s*$//; print if ! $x{$_}++' file
这种变化编辑就地文件:
perl -i -ne 'print if ! $x{$_}++' file
这种变化快速修改的地方文件,使得备份file.bak
perl -i.bak -ne 'print if ! $x{$_}++' file
一内衬安德烈 - 米勒上面贴的作品,除了最新版本的sed的时候输入文件以一个空行,并没有字符结束。 我的Mac上我的CPU只是旋转。
无限循环,如果最后一行是空的,没有字符 :
sed '$!N; /^\(.*\)\n\1$/!P; D'
不挂,但你失去了最后一行
sed '$d;N; /^\(.*\)\n\1$/!P; D'
【解说】在的最后sed的常见问题 :
GNU的sed的维护者认为,尽管便携性问题
这会导致,改变所述N个打印命令(而不是
删除)模式空间是与一个人的直觉更加一致
有关如何命令为“追加下一行” 应该的行为。
另一个事实有利于改变是“{N;指令;}”,将
删除最后一行,如果该文件是奇数行,但
打印的最后一行,如果文件中有偶数行的。要转换其使用N的前行为脚本(删除
在达到EOF)与兼容脚本模式空间
sed的所有版本, 改变一个孤独的“N”; 到“$ d; N;” 。
使用议会(Vi兼容)的另一种方法 :
删除重复的,连续的行从文件中:
vim -esu NONE +'g/\v^(.*)\n\1$/d' +wq
删除文件重复,不连续和非空行:
vim -esu NONE +'g/\v^(.+)$\_.{-}^\1$/d' +wq
$ echo -e '1\n2\n2\n3\n3\n3\n4\n4\n4\n4\n5' |sed -nr '$!N;/^(.*)\n\1$/!P;D'
1
2
3
4
5
其核心思想是:
print ONLY once of each duplicate consecutive lines at its LAST appearance and use D command to implement LOOP.
解释:
$!N;
:如果当前行是不是最后一行,则使用N
命令读取下一行到pattern space
。 /^(.*)\n\1$/!P
:如果当前的内容pattern space
是2个duplicate string
通过分隔\n
,这意味着下一行是same
与电流线,我们不能根据打印我们的核心理念; 否则,这意味着当前行是其所有的重复连续的行的最后的外观,我们现在可以使用P
命令打印字符在当前pattern space
的util \n
( \n
也打印)。 D
:我们使用D
命令删除字符在当前pattern space
的util \n
( \n
也被删除),则内容pattern space
是下一行。 D
命令将强制sed
跳转到其FIRST
命令$!N
而不是从文件中读取或标准输入流的下一行。 $ echo -e '1\n2\n2\n3\n3\n3\n4\n4\n4\n4\n5' |sed -nr 'p;:loop;$!N;s/^(.*)\n\1$/\1/;tloop;D'
1
2
3
4
5
其核心思想是:
print ONLY once of each duplicate consecutive lines at its FIRST appearance and use : command & t command to implement LOOP.
解释:
:loop
命令设置label
命名loop
。 N
到下一行读入pattern space
。 s/^(.*)\n\1$/\1/
删除当前行,如果下一行是同当前行,我们使用s
命令执行delete
操作。 s
成功执行的命令,然后使用tloop
命令力sed
跳转到label
命名的loop
,这将做同样的循环到下一行UTIL有这行没有重复的连续行latest printed
; 否则,使用D
命令来delete
其是与同一行latest-printed line
,并迫使sed
跳到第一命令,其是p
命令,当前的内容pattern space
是下一个新行。 这可以用awk实现
下面这一行会显示独特价值
awk file_name | uniq
您可以输出这些独特的值到一个新文件
awk file_name | uniq > uniq_file_name
新的文件将uniq_file_name只包含唯一值,没有重复
cat filename | sort | uniq -c | awk -F" " '$1<2 {print $2}'
删除使用awk中的重复行。