在bash中基于多个列合并文件
我有一个包含多个列(用逗号分隔)的文件,其中的值重复。我要做的是基于这些列合并或“汇总”行 例如,假设我有以下内容: 输入文件:在bash中基于多个列合并文件,bash,awk,Bash,Awk,我有一个包含多个列(用逗号分隔)的文件,其中的值重复。我要做的是基于这些列合并或“汇总”行 例如,假设我有以下内容: 输入文件: ID, Name , Eye Color, Hair Color, Marital Status 1 , John , Brown , Brown , Single 1 , Mary , Green , Brown , Married 2 , Joe , Blue , Blonde , Divorced 2 , Brian,
ID, Name , Eye Color, Hair Color, Marital Status
1 , John , Brown , Brown , Single
1 , Mary , Green , Brown , Married
2 , Joe , Blue , Blonde , Divorced
2 , Brian, Green , Brown , Single
2 , Gary , Brown , Blonde , Married
我想要基于第一列和第四列的以下输出:
输出文件:
ID, Name , Eye Color, Hair Color, Marital Status, Name, Eye Color, Hair Color, Marital Status
1 , John , Brown , Brown , Single , Mary, Green , Brown , Married
2 , Joe , Blue , Blonde , Divorced , Gary, Brown , Blonde , Married
2 , Brian, Green , Brown , Single
我可以使用以下awk为第一列执行此操作:
awk -F, '
NR!=1 && p1!=$1 { print prev; prev="" }
{ p1=$1; prev=(prev"") ? prev FS substr($0,index($0,$2)) : $0 }
END { if(prev"") print prev }
' input.txt > output.txt
我还需要找到一种方法来包括第四列。这里是一般的想法,不假设记录是有序的(但也不保留顺序) 您可以像在逻辑中一样过滤不需要的重复列,并且需要努力使标题适合匹配记录的最大长度 可以使用扩展标题的格式化版本
$ awk 'BEGIN{FS=" *, *"; OFS=","}
NR==1{$1=$1; header0=$0; split($0,header); next}
{$1=$1; c[$1,$4]++;
a[$1,$4]=(($1,$4) in a?a[$1,$4] OFS $2 OFS $3 OFS $5:$0)}
END{for(k in c) if(max<c[k]) max=c[k];
printf "%s",header0;
for(i=2;i<=max;i++) printf "%s", OFS header[2] OFS header[3] OFS header[5];
print "";
for(k in a) print a[k] | "sort -n" }' file |
column -ts,
ID Name Eye Color Hair Color Marital Status Name Eye Color Marital Status
1 John Brown Brown Single Mary Green Married
2 Brian Green Brown Single
2 Joe Blue Blonde Divorced Gary Brown Married
$awk'开始{FS=“*,*”OFS=“,”}
NR==1{$1=$1;header0=$0;拆分($0,header);下一个}
{$1=$1;c[$1,$4]+;
a[$1,$4]=(a中的($1,$4)OFS$2 OFS$3 OFS$5:$0)}
END{for(k in c)if(max这里是一般的想法,不假设记录是有序的(但也不保留顺序)
您可以像在逻辑中一样过滤不需要的重复列,并且需要努力使标题适合匹配记录的最大长度
可以使用扩展标题的格式化版本
$ awk 'BEGIN{FS=" *, *"; OFS=","}
NR==1{$1=$1; header0=$0; split($0,header); next}
{$1=$1; c[$1,$4]++;
a[$1,$4]=(($1,$4) in a?a[$1,$4] OFS $2 OFS $3 OFS $5:$0)}
END{for(k in c) if(max<c[k]) max=c[k];
printf "%s",header0;
for(i=2;i<=max;i++) printf "%s", OFS header[2] OFS header[3] OFS header[5];
print "";
for(k in a) print a[k] | "sort -n" }' file |
column -ts,
ID Name Eye Color Hair Color Marital Status Name Eye Color Marital Status
1 John Brown Brown Single Mary Green Married
2 Brian Green Brown Single
2 Joe Blue Blonde Divorced Gary Brown Married
$awk'开始{FS=“*,*”OFS=“,”}
NR==1{$1=$1;header0=$0;拆分($0,header);下一个}
{$1=$1;c[$1,$4]+;
a[$1,$4]=(a中的($1,$4)OFS$2 OFS$3 OFS$5:$0)}
END{for(k in c)if(max以下使用三个关联数组跟踪所有内容
x
数组是一个二维“交叉引用”--具有第1列和第4列值的索引,并且具有一个存储值作为行号,我们将在其中查找匹配行
g
数组跟踪我们“增长”特定行的次数。(我们在需要时使用此数组来增长标题。)
o
数组是我们的输出数组,用于聚合数据行
我们使用sprintf
在添加到输出之前重新格式化最后一列输入,以根据问题的输出要求保留表格的间距
awk -F, -v OFS=, '
($1, $4) in x {
# existent row -- append
i = x[$1, $4]
$1 = ""
$5 = sprintf("%-15s", $5)
o[i] = o[i] $0
if(++g[i] > g[1]) {
# grow the header row
o[1] = o[1] h
++g[1]
}
next
}
{
# new output row
x[$1, $4] = ++n
$5 = sprintf("%-15s", $5)
o[n] = $0
}
NR==1 {
# save header for append
$1 = ""
h = $0
}
END {
for (i=1; i<=n; ++i)
print o[i]
}'
awk-F,-v OFS=,'
(1美元,4美元)x{
#现有行—追加
i=x[$1,$4]
$1 = ""
$5=sprintf(“%-15s”,5美元)
o[i]=o[i]$0
if(++g[i]>g[1]){
#增加标题行
o[1]=o[1]h
++g[1]
}
下一个
}
{
#新输出行
x[$1,$4]=++n
$5=sprintf(“%-15s”,5美元)
o[n]=$0
}
NR==1{
#保存要追加的标题
$1 = ""
h=$0
}
结束{
对于(i=1;i,以下使用三个关联数组跟踪所有内容
x
数组是一个二维“交叉引用”--具有第1列和第4列值的索引,并且具有一个存储值作为行号,我们将在其中查找匹配行
g
数组跟踪我们“增长”特定行的次数。(我们在需要时使用此数组来增长标题。)
o
数组是我们的输出数组,用于聚合数据行
我们使用sprintf
在添加到输出之前重新格式化最后一列输入,以根据问题的输出要求保留表格的间距
awk -F, -v OFS=, '
($1, $4) in x {
# existent row -- append
i = x[$1, $4]
$1 = ""
$5 = sprintf("%-15s", $5)
o[i] = o[i] $0
if(++g[i] > g[1]) {
# grow the header row
o[1] = o[1] h
++g[1]
}
next
}
{
# new output row
x[$1, $4] = ++n
$5 = sprintf("%-15s", $5)
o[n] = $0
}
NR==1 {
# save header for append
$1 = ""
h = $0
}
END {
for (i=1; i<=n; ++i)
print o[i]
}'
awk-F,-v OFS=,'
(1美元,4美元)x{
#现有行—追加
i=x[$1,$4]
$1 = ""
$5=sprintf(“%-15s”,5美元)
o[i]=o[i]$0
if(++g[i]>g[1]){
#增加标题行
o[1]=o[1]h
++g[1]
}
下一个
}
{
#新输出行
x[$1,$4]=++n
$5=sprintf(“%-15s”,5美元)
o[n]=$0
}
NR==1{
#保存要追加的标题
$1 = ""
h=$0
}
结束{
对于(i=1;唯一的问题是(我知道它不会出现在这个过于简单的数据中)我不确定需要“汇总”多少组记录到一行。但也许我可以在第一个awk命令后运行类似的操作。这种方法不受限制。您可以计算汇总行数并相应地打印标题,请参阅更新。唯一的问题是(我知道它不会显示在这个过于简化的数据中)我不确定需要“汇总”多少组记录到一行。但也许我可以在第一个awk命令后运行类似的操作。这种方法不受限制。您可以计算汇总行数并相应地打印标题,请参阅更新。