希望仅打印具有重复的第一个字段的行。例如来自这样的数据:
1 abcd
1 efgh
2 ijkl
3 mnop
4 qrst
4 uvwx
应打印出来:
1 abcd
1 efgh
4 qrst
4 uvwx
(仅供参考 - 我的数据中第一个字段的长度不总是1个字符)
答案 0 :(得分:5)
awk 'FNR==NR{a[$1]++;next}(a[$1] > 1)' ./infile ./infile
是的,你给它输入两次相同的文件。由于您事先并不知道当前记录是否为uniq,因此您在第一次传递时基于$1
构建一个数组,然后您只输出多次看到$1
的记录在第二关。
我确信只有一次通过文件才有办法实现,但我怀疑它们会像“干净”一样
FNR==NR
:仅当awk
正在读取第一个文件时才会出现这种情况。它主要测试所看到的记录总数(NR)与当前文件(FNR)中的输入记录。a[$1]++
:构建一个关联数组 a ,其关键是第一个字段($1
),每次看到它的值增加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
答案 1 :(得分:1)
这里有一些awk代码可以执行您想要的操作,假设输入已按其第一个字段分组(如uniq
也需要):
BEGIN {f = ""; l = ""}
{
if ($1 == f) {
if (l != "") {
print l
l = ""
}
print $0
} else {
f = $1
l = $0
}
}
在此代码中,f
是字段1的前一个值,l
是该组的第一行(如果已经打印出来,则为空)。
答案 2 :(得分:1)
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
}
答案 3 :(得分:0)
假设您在问题中显示的有序输入:
awk '$1 == prev {if (prevline) print prevline; print $0; prevline=""; next} {prev = $1; prevline=$0}' inputfile
该文件只需要读一次。
答案 4 :(得分:0)
如果你可以使用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