如何在不知道电子邮件地址的情况下以CSV格式通过电子邮件进行分组



我有一个CSV,它有不同的列,其中一列包括电子邮件。脚本应该根据列生成一个字符串,并将其作为附加列添加到CSV中。此时,脚本会贯穿每一行并形成字符串。但我想要的是,该脚本只构建具有相同电子邮件地址的行字符串。棘手的是,我不知道不同的电子邮件地址,所以我不能硬编码并动态分组。

有什么方法可以实现这一点?

这是我的初始CSV:

42342;home;2020-01-12;2020-01-13;test@test.com
45235;home;2020-04-12;2020-04-13;test@test.com
68787;photo;2020-05-12;2020-05-13;email@test.com
68787;test;2020-05-12;2020-05-13;moritz@test.com
68787;test;2020-05-12;2020-05-13;moritz@test.com
68787;test;2020-05-12;2020-05-13;moritz@test.com

CSV最后应该是什么样子:

42342;home;2020-01-12;2020-01-13;test@test.com;home 2020-01-12_2020-01-13 && home 2020-04-12_2020-04-13
45235;home;2020-04-12;2020-04-13;test@test.com;home 2020-01-12_2020-01-13 && home 2020-04-12_2020-04-13
68787;photo;2020-05-12;2020-05-13;email@test.com;photo 2020-05-12_2020-05-13
68787;test;2020-05-12;2020-05-13;moritz@test.com;test 2020-05-12_2020-05-13 && test 2020-05-12_2020-05-13 && test 2020-05-12_2020-05-13
68787;test;2020-05-12;2020-05-13;moritz@test.com;test 2020-05-12_2020-05-13 && test 2020-05-12_2020-05-13 && test 2020-05-12_2020-05-13
68787;test;2020-05-12;2020-05-13;moritz@test.com;test 2020-05-12_2020-05-13 && test 2020-05-12_2020-05-13 && test 2020-05-12_2020-05-13

这是我的bash脚本:

getPhotosCommand(){
com=""
header="ID;DIR;START_DATE;END_DATE" 

while read line; do
IFS=';' read -r -a array <<< "$line"
dir=${array[2]}
start_date=${array[3]}
end_date=${array[4]}
newCom="$dir $start_date_$end_date && "
com=$com$newCom

done < $file_new_photos

echo $com
}

一个保持原始行顺序的两遍awk解决方案。第一步是构建第六个字段(针对每个电子邮件(,第二步是将它们附加到相应的行中。

awk '
BEGIN {FS = OFS = ";"}
{
if (NR == FNR) {
str = $2 " " $3 " " $4
if (arr[$5]) {
arr[$5] = arr[$5] " && " str
} else {
arr[$5] = str
}
} else {
print $0, arr[$5]
}
}
' file.scsv file.scsv

输出:

42342;home;2020-01-12;2020-01-13;test@test.com;home 2020-01-12 2020-01-13 && home 2020-04-12 2020-04-13
45235;home;2020-04-12;2020-04-13;test@test.com;home 2020-01-12 2020-01-13 && home 2020-04-12 2020-04-13
68787;photo;2020-05-12;2020-05-13;email@test.com;photo 2020-05-12 2020-05-13
68787;test;2020-05-12;2020-05-13;moritz@test.com;test 2020-05-12 2020-05-13 && test 2020-05-12 2020-05-13 && test 2020-05-12 2020-05-13
68787;test;2020-05-12;2020-05-13;moritz@test.com;test 2020-05-12 2020-05-13 && test 2020-05-12 2020-05-13 && test 2020-05-12 2020-05-13
68787;test;2020-05-12;2020-05-13;moritz@test.com;test 2020-05-12 2020-05-13 && test 2020-05-12 2020-05-13 && test 2020-05-12 2020-05-13

为了解析一个文件并输出另一个经过后期处理的文件,我会使用awk。

Awk有关联数组(在大多数语言中也称为map(,它可能会帮助你完成任务。

简而言之,你的awk脚本应该是:

  • 在开始块中:初始化关联数组,处理一些参数以设置结束块中的输出
  • 在您的";行块":在关联数组中插入当前行,并将电子邮件作为关键字
  • 在结束块中:生成在关联数组上循环的新文件

玩得开心=(

假设行按电子邮件地址分组,并且文件没有空行,那么这个bash脚本可能就是您要做的。

#!/bin/bash
cnt=0
while IFS= read -r line; do
email=${line##*;}
if [ "$email" = "$prev_email" ]; then
grpline[cnt++]=$line
else
if ((cnt)); then
tail=
for ((i = 0; i < cnt; ++i)); do
IFS=';' read -ra fld <<< "${grpline[i]}"
tail+=" && ${fld[1]} ${fld[2]}_${fld[3]}"
done
tail=${tail:4}
for ((i = 0; i < cnt; ++i)); do
printf '%s;%sn' "${grpline[i]}" "$tail"
done
fi
prev_email=$email
grpline[0]=$line
cnt=1
fi
done < <(cat file; echo)

如果文件未按电子邮件地址分组,则用sort -t ; -k5 file替换cat file

最新更新