Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell sed或awk:按2列分组并获取另一列的最后一个值_Shell_Awk_Sed_Group By_Aggregation - Fatal编程技术网

Shell sed或awk:按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 考虑到您的输入_文件和所示的示例以及第一个和第三个字段的排序方法相同,下

我需要快速处理一个有很多冗余的文本文件。 我可以使用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

考虑到您的输入_文件和所示的示例以及第一个和第三个字段的排序方法相同,下面的内容可能会对您有所帮助

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
和GNU
sort

$ 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