我有以下文件:
2
1
4
3
2
1
Run Code Online (Sandbox Code Playgroud)
我想要这样的输出(没有任何重复项并保留顺序的唯一行):
4
3
Run Code Online (Sandbox Code Playgroud)
我尝试过sort file.txt | uniq -u
它有效,但输出已排序:
3
4
Run Code Online (Sandbox Code Playgroud)
我尝试awk '!x[$0]++' file.txt
保持顺序,但它会打印一次所有值:
2
1
4
3
Run Code Online (Sandbox Code Playgroud)
mar*_*rkp 14
有几个想法可供选择:
a)读取输入文件两次:
awk '
FNR==NR { counts[$0]++; next } # 1st pass: keep count
counts[$0] == 1 # 2nd pass: print rows with count == 1
' file.txt file.txt
Run Code Online (Sandbox Code Playgroud)
b)读取输入文件一次:
awk '
{ lines[NR] = $0 # maintain ordering of rows
counts[$0]++
}
END { for ( i=1;i<=NR;i++ ) # run thru the indices of the lines[] array and ...
if ( counts[lines[i]] == 1 ) # if the associated count == 1 then ...
print lines[i] # print the array entry to stdout
}
' file.txt
Run Code Online (Sandbox Code Playgroud)
这两者都会生成:
4
3
Run Code Online (Sandbox Code Playgroud)
pmf*_*pmf 10
我尝试过
sort file.txt | uniq -u
它有效,但输出已排序
grep -f
您可以获取该输出,并将其用作原始文件上的换行符分隔模式列表。用于-Fx
将模式视为整行固定字符串(而不是正则表达式)。
sort file.txt | uniq -u | grep -Fxf- file.txt
Run Code Online (Sandbox Code Playgroud)
4
3
Run Code Online (Sandbox Code Playgroud)
这是一个 Ruby 来做到这一点:
ruby -lne 'BEGIN{cnt=Hash.new {|h,k| h[k] = 0} }
cnt[$_]+=1
END{puts cnt.select{|k,v| v==1}.keys.join("\n") }
' file
Run Code Online (Sandbox Code Playgroud)
印刷:
4
3
Run Code Online (Sandbox Code Playgroud)
或者,在一次读取文件中:
ruby -e 'puts $<.read.split(/\R+/).
group_by{|x| x}.select{|k,v| v.length==1}.keys.join("\n")
' file
# same output
Run Code Online (Sandbox Code Playgroud)
与 awk 不同,Ruby 关联数组维护插入顺序。
如果你想要一张通行证,awk
你可以这样做:
awk 'BEGIN{OFS="\t"}
{ if (seen[$0]++) delete order[$0]; else order[$0]=FNR }
END { for ( e in order ) print order[e], e } ' file | sort -nk 1,1 | cut -f2-
# same output
Run Code Online (Sandbox Code Playgroud)
(感谢 Ed Morton 提供了更好的 awk!)