我有一些非常大的表,我需要提取特定的行。我用一个简单的例子来说明这个任务。假设,我称了一些苹果、香蕉和橙子的重量。我需要提取最小的苹果、香蕉和橙子的重量
原表:
Apple 3
Banana 8
Orange 2
Apple 7
Banana 9
Orange 13
Apple 9
Banana 1
Orange 11
期望的输出:
Apple 3
Banana 1
Orange 2
答案1
和gnu
datamash
:
datamash -s -g 1 min 2 <infile
苹果3 香蕉 1 橙2
此操作按st 字段s
进行排序和g
分组,为第一个字段中的每个 ID 打印 nd 字段中的值。它假设字段由单个制表符分隔。如果它们由多个空格分隔或定义另一个字段分隔符(例如单个空格),则使用:1
min
2
-W, --whitespace
-t, --field-separator=
datamash -t' ' -s -g 1 min 2 <infile
由于datamash
需要排序输入,因此输出也将按第一个字段排序。
答案2
和awk
:
$ awk '($2<a[$1] || !a[$1]){a[$1]=$2}END{for(f in a){print f,a[f]}}' file
Orange 2
Banana 1
Apple 3
a[$1]=$2
设置一个名为 的数组a
,其键是第一个字段,其值是第二个字段。如果 i) 它小于存储的值或 ii) 没有存储值,上面的脚本会将第二个字段保存为数组中第一个字段的值。该END
块迭代数组并打印其内容。
使用 GNU sort
:
$ sort -nk2 file | sort -u -k1,1
Apple 3
Banana 1
Orange 2
第一种排序将以权重升序(第二个字段)打印行,第二种排序将仅保留唯一的行,但仅检查第一个字段。结果是打印每个字符串的第一次出现,由于第一次排序,该字符串将是该水果的最小值。
还有一个(稍微)短一点的 Perl:
$ perl -lane '$k{$F[0]}//=$F[1]; $k{$F[0]}=$F[1] if $F[1]<$k{$F[0]};
END{print "$_ $k{$_}" for keys(%k)}' file
Orange 2
Apple 3
Banana 1
//=
除非变量已经有一个值,否则将分配一个值。然后,做法就和awk
上面一样了。我们创建一个散列,%k
其键是水果,其值是权重,并保存最小值。该-a
标志的作用perl
类似于awk
将空格上的输入拆分到@F
数组中。
答案3
您可以使用 perl oneliner 来完成此操作:
perl -ane '$h{$F[0]} = $F[1] if (!defined $h{$F[0]} || $h{$F[0]} > $F[1]);
END {foreach (keys %h) {print "$_ $h{$_}\n"}}' fruits_list.txt
这里我们使用哈希映射(%h)来存储元素。如果水果尚未存在于哈希中,我们将添加其第一个值,如果它已经存在,则仅当该值小于已存储的值时我们才更新该值。 END 块仅在处理文件的最后一行后执行,它打印哈希图。
答案4
sort -k2,2n file | sort -u -k1,1
输出:
苹果3 香蕉 1 橙2