我怎样才能删除每行中的重复项,例如这里?
1 1 1 2 1 2 3
5 5 4 1 2 3 3
我想获得这个输出:
1 2 3
5 4 1 2 3
有很多行(100,000),并且我希望每行都有唯一的值。Perl 可能是最快的,但是如何在 Perl 或 Bash 中做到这一点?
答案1
以下是使用 awk 的一个选项:
awk '{ while(++i<=NF) printf (!a[$i]++) ? $i FS : ""; i=split("",a); print ""}' infile > outfile
编辑更新了评论:
while (++i<=NF)
初始化 while 循环,由于 $0 是 awk 中的完整行,因此预先增加“i”。
因此它从 $1(第一个字段)开始。循环遍历行直到行末(小于或等于 awk 中内置的“字段数”的“NF”)。默认字段分隔符是空格,您可以轻松更改默认分隔符。
printf (!a[$i]++) ? $i FS : ""
这是一个三元运算。
因此,如果输入不在数组中
!a[$i]++
,则打印 $i,如果在数组中,则打印“”。(如果不喜欢这种方式,可以删除!
并反转)。$i FS : ""
i=split("",a)
通常,这是一个空分割。在这种情况下,它会重置 I 以进行下一行。
print ""
结束输出行(实际上不是 100% 知道为什么),否则您将得到以下输出:
1 2 3 5 4 1 2 3
代替
1 2 3
5 4 1 2 3
答案2
由于ruby
我所知道的任何 Linux 发行版都附带:
ruby -e 'STDIN.readlines.each { |l| l.split(" ").uniq.each { |e| print "#{e} " }; print "\n" }' < test
这里test
是包含元素的文件。
为了解释这个命令的作用 — — 尽管 Ruby 几乎可以从左到右阅读:
- 读取输入(来自
< test
你的 shell) - 浏览输入的每一行
- 根据分隔项之间的一个空格将行拆分为数组 (
split(" ")
) - 从该数组中获取唯一元素(按顺序)
- 对于每个唯一元素,打印它,包括空格(
print "#{e} "
) - 处理完唯一元素后,打印换行符
答案3
不是纯粹的 bash,但是...:
while read line; do
printf "%s\n" $line | sort -u | tr '\n' ' '
echo ''
done < file
这些行将作为副产品进行分类。