Jon*_*röm 259
awk '!seen[$0]++' file.txt
Run Code Online (Sandbox Code Playgroud)
seen是一个关联数组,Awk将传递文件的每一行.如果一行不在数组中,那么seen[$0]将评估为false.这!是一个逻辑NOT运算符,将false反转为true.Awk将打印表达式求值为true的行.的++增量seen,以便seen[$0] == 1在第一时间线被发现,在此之后seen[$0] == 2,依此类推.
Awk评估除了0和""(空字符串)之外的所有内容.如果重复线路被放置在seen随后!seen[$0]将评估为false,该线路将不会被写入到输出.
And*_*ler 29
来自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'
Run Code Online (Sandbox Code Playgroud)
Chr*_*nat 12
类似于@ jonas的awk解决方案的Perl单线程:
perl -ne 'print if ! $x{$_}++' file
Run Code Online (Sandbox Code Playgroud)
此变体在比较之前删除尾随空格:
perl -lne 's/\s*$//; print if ! $x{$_}++' file
Run Code Online (Sandbox Code Playgroud)
此变体就地编辑文件:
perl -i -ne 'print if ! $x{$_}++' file
Run Code Online (Sandbox Code Playgroud)
此变体就地编辑文件,并进行备份 file.bak
perl -i.bak -ne 'print if ! $x{$_}++' file
Run Code Online (Sandbox Code Playgroud)
使用 Vim(Vi compatible) 的另一种方法:
从文件中删除重复的连续行:
vim -esu NONE +'g/\v^(.*)\n\1$/d' +wq
从文件中删除重复的、不连续的和非空的行:
vim -esu NONE +'g/\v^(.+)$\_.{-}^\1$/d' +wq
安德烈米勒上面发布的单线工作除了最近版本的sed时,输入文件以空行结束且没有字符.在我的Mac上我的CPU只是旋转.
如果最后一行为空且没有字符,则为无限循环:
sed '$!N; /^\(.*\)\n\1$/!P; D'
不挂,但你失去了最后一行
sed '$d;N; /^\(.*\)\n\1$/!P; D'
解释是在sed FAQ的最后:
GNU sed维护者认为,尽管
这会导致可移植性问题,但更改N命令以打印(而不是
删除)模式空间更符合人们
对"追加下一行"命令应如何表现的直觉.
另一个有利于改变的事实是"{N; command;}"将
删除最后一行,如果文件具有奇数行,但如果文件具有偶数行,则
打印最后一行.要将使用N的前一种行为的脚本(
在到达EOF时删除模式空间)转换为与
所有sed版本兼容的脚本,请更改单独的"N"; 到"$ d; N;" .
$ 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
Run Code Online (Sandbox Code Playgroud)
核心思想是:
在每个重复的连续行的最后一次出现时仅打印一次,并使用 D 命令来实现循环。
解释:
$!N;:如果当前行不是最后一行,则使用该N命令将下一行读入模式空间。/^(.*)\n\1$/!P:如果当前模式空间的内容是由 分隔的两个重复字符串\n,这意味着下一行与当前行相同,根据我们的核心思想,我们不能打印它;否则,这意味着当前行是其所有重复连续行的最后一次出现。我们现在可以使用该命令打印当前模式空间P中的字符,直到(也打印出来)。\n\nD:我们使用该命令删除当前模式空间D中的字符,直到(也删除),然后模式空间的内容就是下一行。\n\nD命令将强制sed跳转到其第一个命令$!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
Run Code Online (Sandbox Code Playgroud)
核心思想是:
每个重复的连续行在第一次出现时只打印一次,并使用命令和命令来实现LOOP。
:t
解释:
:loop命令设置一个名为loop的标签。N将下一行读入模式空间。s/^(.*)\n\1$/\1/如果下一行与当前行相同,则用于删除当前行。我们使用该s命令来执行删除操作。s命令执行成功,则使用tloop命令强制sed跳转到名为loop的标签处,对下一行进行同样的循环,直到最后打印的行没有重复的连续行为止;否则,使用命令到与最新打印的行相同的行,并强制跳转到第一条命令,即命令。当前模式空间的内容是下一个新行。Ddeletesedp