Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 对文本文件进行重复数据消除,并将最后一次出现的内容保留在一个输出文件中,然后将其他内容移动到另一个输出文件中_Linux_Unix_Awk_Sua - Fatal编程技术网

Linux 对文本文件进行重复数据消除,并将最后一次出现的内容保留在一个输出文件中,然后将其他内容移动到另一个输出文件中

Linux 对文本文件进行重复数据消除,并将最后一次出现的内容保留在一个输出文件中,然后将其他内容移动到另一个输出文件中,linux,unix,awk,sua,Linux,Unix,Awk,Sua,我有一个包含DUP记录的文件(DUP在列中)。我只想在一个文件中保留最后一次出现的dup记录,并将所有其他dup移动到另一个文件中 文件:输入 foo j bar bn bar b bar bn bar bn bar bn kkk hh fjk ff foo jj xxx tt kkk hh 我使用了以下awk语句来保留最后一个事件-- 文件:输出 foo jj xxx tt fjk ff kkk hh bar bn 如何将重复记录移动到另一个文件(保留最后一个事件) 在一个文件中移动foo

我有一个包含DUP记录的文件(DUP在列中)。我只想在一个文件中保留最后一次出现的dup记录,并将所有其他dup移动到另一个文件中

文件:输入

foo j
bar bn
bar b
bar bn
bar bn
bar bn
kkk hh
fjk ff
foo jj
xxx tt
kkk hh
我使用了以下awk语句来保留最后一个事件--

文件:输出

foo jj
xxx tt
fjk ff
kkk hh
bar bn
如何将重复记录移动到另一个文件(保留最后一个事件)

在一个文件中移动
fooj
,比如d_输出
foo jj
保存在输出文件中

一个技巧是使用
tac
首先反转文件(第一个匹配比最后一个更容易获得):

编辑:

以下是超过一百万条生产线的当前3种解决方案的基准数据:

sudo_o

real    0m2.156s
user    0m1.004s
sys     0m0.117s

kent

real    0m2.806s
user    0m2.718s
sys     0m0.080s

scrutinizer

real    0m4.033s
user    0m3.939s
sys     0m0.082s
在这里验证

在我的本地计算机上,使用文件
seq 1 1000000>bench

# sudo_o
$ time tac bench | awk 'a[$1]++{print $0 > "dup";next}{print $0 > "output"}' 

real    0m0.729s
user    0m0.668s
sys     0m0.101s

# scrutinizer
$ time awk 'NR==FNR{A[$1]=NR; next} A[$1]!=FNR{print>f; next}1' f=dups bench bench > output

real    0m1.093s
user    0m1.016s
sys     0m0.070s

# kent 
$ time awk '$1 in a{print a[$1]>"dup.txt"}{a[$1]=$0}END{for(x in a)print a[x]}' bench > output

real    0m1.141s
user    0m1.055s
sys     0m0.080s

一个技巧是使用
tac
首先反转文件(第一个匹配比最后一个更容易抓取):

编辑:

以下是超过一百万条生产线的当前3种解决方案的基准数据:

sudo_o

real    0m2.156s
user    0m1.004s
sys     0m0.117s

kent

real    0m2.806s
user    0m2.718s
sys     0m0.080s

scrutinizer

real    0m4.033s
user    0m3.939s
sys     0m0.082s
在这里验证

在我的本地计算机上,使用文件
seq 1 1000000>bench

# sudo_o
$ time tac bench | awk 'a[$1]++{print $0 > "dup";next}{print $0 > "output"}' 

real    0m0.729s
user    0m0.668s
sys     0m0.101s

# scrutinizer
$ time awk 'NR==FNR{A[$1]=NR; next} A[$1]!=FNR{print>f; next}1' f=dups bench bench > output

real    0m1.093s
user    0m1.016s
sys     0m0.070s

# kent 
$ time awk '$1 in a{print a[$1]>"dup.txt"}{a[$1]=$0}END{for(x in a)print a[x]}' bench > output

real    0m1.141s
user    0m1.055s
sys     0m0.080s

tac
rev
这样的工具很不错!。但是,它们并不是所有发行版的默认版本,特别是我发现您已经用
unix
标记了这个问题。另外,
tac
更改输出/dup.txt顺序,如果应该保留该顺序,则需要额外的努力来维护该顺序

试试这句话:

awk '$1 in a{print a[$1]>"dup.txt"}{a[$1]=$0}END{for(x in a)print a[x]}' file
以你的例子:

kent$  awk '$1 in a{print a[$1]>"dup.txt"}{a[$1]=$0}END{for(x in a)print a[x]}' file
foo jj
xxx tt
fjk ff
kkk hh
bar bn

kent$  cat dup.txt 
bar bn
bar b
bar bn
bar bn
foo j
kkk hh

tac
rev
这样的工具很不错!。但是,它们并不是所有发行版的默认版本,特别是我发现您已经用
unix
标记了这个问题。另外,
tac
更改输出/dup.txt顺序,如果应该保留该顺序,则需要额外的努力来维护该顺序

试试这句话:

awk '$1 in a{print a[$1]>"dup.txt"}{a[$1]=$0}END{for(x in a)print a[x]}' file
以你的例子:

kent$  awk '$1 in a{print a[$1]>"dup.txt"}{a[$1]=$0}END{for(x in a)print a[x]}' file
foo jj
xxx tt
fjk ff
kkk hh
bar bn

kent$  cat dup.txt 
bar bn
bar b
bar bn
bar bn
foo j
kkk hh

您可以尝试另一个选项,通过读取输入文件两次来保持顺序:

awk 'NR==FNR{A[$1]=NR; next} A[$1]!=FNR{print>f; next}1' f=dups file file
输出:

bar bn
fjk ff
foo jj
xxx tt
kkk hh
副本:

$ cat dups
foo j
bar bn
bar b
bar bn
bar bn
kkk hh

@Sudo_O@williampersell@user2018441。Sudo_O感谢您的性能测试。我试图在我的系统上复制它们,但它没有可用的
tac
,所以我用Kent的版本和我的版本进行了测试,但我无法在我的系统上复制这些差异

更新:我用Sudo_O的版本测试了
cat
而不是
tac
。虽然在带有
tac
的系统上,
tac
cat
在输出到/dev/null时存在0.2秒的差异(参见本文底部)

我得到:

Sudo_O
$ time cat <(seq 1 1000000) | awk 'a[$1]++{print $0 > "/dev/null";next}{print $0 > "/dev/null"}'

real    0m1.491s
user    0m1.307s
sys     0m0.415s

kent
$ time awk '$1 in a{print a[$1]>"/dev/null"}{a[$1]=$0}END{for(x in a)print a[x]}' <(seq 1 1000000) > /dev/null

real    0m1.238s
user    0m1.421s
sys     0m0.038s

scrutinizer
$ time awk 'NR==FNR{A[$1]=NR; next} A[$1]!=FNR{print>f; next}1' f=/dev/null <(seq 1 1000000) <(seq 1 1000000) > /dev/null

real    0m1.422s
user    0m1.778s
sys     0m0.078s
可能是由于缓存效应,较大的文件也会出现缓存效应。。创建内嵌需要:

$ time seq 1 1000000 > infile

real    0m0.224s
user    0m0.213s
sys     0m0.010s

在不同系统上测试:

$ time cat <(seq 1 1000000) > /dev/null

real    0m0.764s
user    0m0.719s
sys     0m0.031s
$ time tac <(seq 1 1000000) > /dev/null

real    0m1.011s
user    0m0.820s
sys     0m0.082s
$time cat/dev/null
实际0.764s
用户0m0.719s
系统0m0.031s
$time-tac/dev/null
实0m1.011s
用户0.820s
系统0m0.082s

您可以尝试的另一个选项,通过读取输入文件两次来保持顺序:

awk 'NR==FNR{A[$1]=NR; next} A[$1]!=FNR{print>f; next}1' f=dups file file
输出:

bar bn
fjk ff
foo jj
xxx tt
kkk hh
副本:

$ cat dups
foo j
bar bn
bar b
bar bn
bar bn
kkk hh

@Sudo_O@williampersell@user2018441。Sudo_O感谢您的性能测试。我试图在我的系统上复制它们,但它没有可用的
tac
,所以我用Kent的版本和我的版本进行了测试,但我无法在我的系统上复制这些差异

更新:我用Sudo_O的版本测试了
cat
而不是
tac
。虽然在带有
tac
的系统上,
tac
cat
在输出到/dev/null时存在0.2秒的差异(参见本文底部)

我得到:

Sudo_O
$ time cat <(seq 1 1000000) | awk 'a[$1]++{print $0 > "/dev/null";next}{print $0 > "/dev/null"}'

real    0m1.491s
user    0m1.307s
sys     0m0.415s

kent
$ time awk '$1 in a{print a[$1]>"/dev/null"}{a[$1]=$0}END{for(x in a)print a[x]}' <(seq 1 1000000) > /dev/null

real    0m1.238s
user    0m1.421s
sys     0m0.038s

scrutinizer
$ time awk 'NR==FNR{A[$1]=NR; next} A[$1]!=FNR{print>f; next}1' f=/dev/null <(seq 1 1000000) <(seq 1 1000000) > /dev/null

real    0m1.422s
user    0m1.778s
sys     0m0.078s
可能是由于缓存效应,较大的文件也会出现缓存效应。。创建内嵌需要:

$ time seq 1 1000000 > infile

real    0m0.224s
user    0m0.213s
sys     0m0.010s

在不同系统上测试:

$ time cat <(seq 1 1000000) > /dev/null

real    0m0.764s
user    0m0.719s
sys     0m0.031s
$ time tac <(seq 1 1000000) > /dev/null

real    0m1.011s
user    0m0.820s
sys     0m0.082s
$time cat/dev/null
实际0.764s
用户0m0.719s
系统0m0.031s
$time-tac/dev/null
实0m1.011s
用户0.820s
系统0m0.082s


awk中关联数组的顺序是任意的,所以您关于顺序的观点也是moot.dup.txt?有一个斜杠(或)。awk中关联数组的顺序是任意的,所以您关于顺序的观点也是moot.dup.txt?有一个斜杠(或)。谢谢Sudo_O。对于1GB这样的大文件,性能如何?awk只查看每一行一次,所以它应该表现得很好,监查者的答案必须通过两次填充,所以对于大文件可能不是最好的。在这个解决方案中,文件也会被读取两次(tac once和awk once)@williampersell是的,但是
tac
可以忽略不计。监查者的解决方案比我的慢2秒。下面是基准数据@ ExcutiNulter我用文件添加了我的本地机器的数字,你的解决方案和肯特的性能相当,但我仍然是我的两倍慢。F.Y.I使用
seq 1 1000000
/dev/null
是为了绕过ideone的文件权限限制。谢谢Sudo_O。对于1GB这样的大文件,性能会如何?awk只查看每一行一次,所以它应该表现得很好,监查者的答案必须通过两次填充,因此对于大型文件可能不是最好的。在此解决方案中,文件也会被读取两次(tac一次,awk一次)。@williampersell是,但
tac
可以忽略不计。监查者的解决方案比我的慢2秒。下面是基准数据@ ExcutiNulter我用文件添加了我的本地机器的数字,你的解决方案和肯特的性能相当,但我仍然是我的两倍慢。F.Y.I使用
seq 1 1000000
/dev/null
是为了绕过ideone的文件权限限制。我假设
tac |……
的性能损失与
cat |……
的顺序相同。应该对我的解决方案的性能给出粗略(独立)的估计。@sudo_O我使用
cat
而不是
tac
添加了您的版本,我假设性能