Shell sed或awk:按2列分组并获取另一列的最后一个值
我需要快速处理一个有很多冗余的文本文件。 我可以使用python,但我认为最简单、最快的方法是在unix shell中使用awk、sed或perl 数据有3列,我需要按(唯一)列1和3分组,然后得到第2列的最后一个值Shell sed或awk:按2列分组并获取另一列的最后一个值,shell,awk,sed,group-by,aggregation,Shell,Awk,Sed,Group By,Aggregation,我需要快速处理一个有很多冗余的文本文件。 我可以使用python,但我认为最简单、最快的方法是在unix shell中使用awk、sed或perl 数据有3列,我需要按(唯一)列1和3分组,然后得到第2列的最后一个值 1,2,3 a 1 A a 2 A a 3 A b 2 C b 3 C b 3 D c 1 C c 1 D c 2 D 结果应该是: 1,2,3 a A 3 b C 3 b D 3 c C 1 c D 2 考虑到您的输入_文件和所示的示例以及第一个和第三个字段的排序方法相同,下
1,2,3
a 1 A
a 2 A
a 3 A
b 2 C
b 3 C
b 3 D
c 1 C
c 1 D
c 2 D
结果应该是:
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
考虑到您的输入_文件和所示的示例以及第一个和第三个字段的排序方法相同,下面的内容可能会对您有所帮助
awk '
FNR==1{
print;
next
}
!a[$1,$3]++{
if(a[prev]){
print prev,a[prev]};
a[$1,$3]=$2
}
{
prev=$1 FS $3
}
END{
if(a[prev] && prev){
print prev,a[prev]
}}
' SUBSEP=" " Input_file
输出如下:
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
您可以使用此
awk
:
awk '{key=$1 FS $3} !(key in arr){a[++n]=key} {arr[key]=$2}
END{for (i=1; i<=n; i++) print a[i], arr[a[i]]}' file
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
awk'{key=$1fs$3}!(arr中的键){a[++n]=key}{arr[key]=2}
END{for(i=1;i这类任务有一个专用工具-datamash
:
不带标题的部分解决方案:
保留标题的完整解决方案:
使用tac
和GNUsort
$ tac Group_Data | sort -u -k1,1 -k3 | awk '{if (NR == 1) print $0; else print $1,$3,$2}'
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
IMO python dictionary和强大的函数使python与任何其他类似的解决方案一样快速和具有竞争力,特别是当您打算使用python进一步处理下游数据时。下面的项目通过使用它们作为python dictionary的键进行分组,然后按第一个和第二个元素进行排序
>>> groupdict = {}
>>> with open("Group_Data") as fp:
... for ii, lines in enumerate(fp):
... if ii == 0:
... header = lines.rstrip()
... else:
... fields = lines.split()
... groupdict[(fields[0],fields[2])] = fields[1]
...
>>> groupdict
{('b', 'C'): '3', ('a', 'A'): '3', ('c', 'D'): '2', ('c', 'C'): '1', ('b', 'D'): '3'}
>>> for ii,elem in enumerate(sorted(groupdict.items(), key = lambda x : (x[0],x[1]))):
... if ii == 0:
... print header
... key, value = elem
... print key[0],key[1],value
...
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
使用tac
的替代解决方案:tac文件| awk'!seen[$1,$3]+{print$1,$3,$2}'| tac
你好,anubhava,谢谢你简洁的解决方案。你能给我一个关于awk“seen”的简要解释吗在替代解决方案中,seen
是一个组合键为$1,$3
的关联数组。Expression!seen[$1,$3]++
在seen
数组中不存在组合键时,存储一个值1
。这样我们只打印给定键的第一次出现和$2
(因为我们已经使用tac
反转了文件)
cat <(head -n 1 input.txt) <(tail -n +2 input.txt | datamash -W -t' ' -g 1,3 last 2)
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
$ tac Group_Data | sort -u -k1,1 -k3 | awk '{if (NR == 1) print $0; else print $1,$3,$2}'
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2
>>> groupdict = {}
>>> with open("Group_Data") as fp:
... for ii, lines in enumerate(fp):
... if ii == 0:
... header = lines.rstrip()
... else:
... fields = lines.split()
... groupdict[(fields[0],fields[2])] = fields[1]
...
>>> groupdict
{('b', 'C'): '3', ('a', 'A'): '3', ('c', 'D'): '2', ('c', 'C'): '1', ('b', 'D'): '3'}
>>> for ii,elem in enumerate(sorted(groupdict.items(), key = lambda x : (x[0],x[1]))):
... if ii == 0:
... print header
... key, value = elem
... print key[0],key[1],value
...
1,2,3
a A 3
b C 3
b D 3
c C 1
c D 2