【发布时间】:2011-07-04 16:11:30
【问题描述】:
希望仅打印具有重复第一个字段的行。例如来自如下所示的数据:
1 abcd
1 efgh
2 ijkl
3 mnop
4 qrst
4 uvwx
应该打印出来:
1 abcd
1 efgh
4 qrst
4 uvwx
(仅供参考 - 我的数据中的第一个字段并不总是 1 个字符)
【问题讨论】:
希望仅打印具有重复第一个字段的行。例如来自如下所示的数据:
1 abcd
1 efgh
2 ijkl
3 mnop
4 qrst
4 uvwx
应该打印出来:
1 abcd
1 efgh
4 qrst
4 uvwx
(仅供参考 - 我的数据中的第一个字段并不总是 1 个字符)
【问题讨论】:
awk 'FNR==NR{a[$1]++;next}(a[$1] > 1)' ./infile ./infile
是的,你给它两次输入相同的文件。由于您不提前知道当前记录是否为 uniq,因此您在第一次通过时基于 $1 构建一个数组,然后您只输出在第二次通过时多次看到 $1 的记录.
我确信有一些方法可以只通过文件一次,但我怀疑它们会像“干净”一样“干净”
FNR==NR:这仅在awk 正在读取第一个文件时才成立。它实质上是测试看到的记录总数 (NR) 与当前文件中的输入记录 (FNR)。a[$1]++:构建一个关联数组a,其中的键是第一个字段 ($1),每次看到它的值都会增加一个。next:如果达到此条件,请忽略脚本的其余部分,从新的输入记录重新开始(a[$1] > 1) 这只会在./infile 的第二次通过时评估,并且它只打印我们不止一次看到的第一个字段 ($1) 的记录。本质上,它是if(a[$1] > 1){print $0} 的简写
$ cat ./infile
1 abcd
1 efgh
2 ijkl
3 mnop
4 qrst
4 uvwx
$ awk 'FNR==NR{a[$1]++;next}(a[$1] > 1)' ./infile ./infile
1 abcd
1 efgh
4 qrst
4 uvwx
【讨论】:
假设输入已经按其第一个字段分组(如uniq 也需要),这里有一些 awk 代码可以执行您想要的操作:
BEGIN {f = ""; l = ""}
{
if ($1 == f) {
if (l != "") {
print l
l = ""
}
print $0
} else {
f = $1
l = $0
}
}
在此代码中,f 是字段 1 的前一个值,l 是组的第一行(如果已经打印出来,则为空)。
【讨论】:
BEGIN { IDLE = 0; DUP = 1; state = IDLE }
{
if (state == IDLE) {
if($1 == lasttime) {
state = DUP
print lastline
} else state = IDLE
} else {
if($1 != lasttime)
state = IDLE
}
if (state == DUP)
print $0
lasttime = $1
lastline = $0
}
【讨论】:
假设您在问题中显示的有序输入:
awk '$1 == prev {if (prevline) print prevline; print $0; prevline=""; next} {prev = $1; prevline=$0}' inputfile
文件只需读取一次。
【讨论】:
如果你可以使用 Ruby(1.9+)
#!/usr/bin/env ruby
hash = Hash.new{|h,k|h[k] = []}
File.open("file").each do |x|
a,b=x.split(/\s+/,2)
hash[a] << b
end
hash.each{|k,v| hash[k].each{|y| puts "#{k} #{y}" } if v.size>1 }
输出:
$ cat file
1 abcd
1 efgh
2 ijkl
3 mnop
4 qrst
4 uvwx
4 asdf
1 xzzz
$ ruby arrange.rb
1 abcd
1 efgh
1 xzzz
4 qrst
4 uvwx
4 asdf
【讨论】: