【问题标题】:Search duplicates in a column, add value在列中搜索重复项,添加值
【发布时间】:2021-02-11 12:45:46
【问题描述】:

转换文件 input.csv。

id,location_id,organization_id,service_id,name,title,email,department
36,,,22,Joe Smith,third-party,john.smith@example.org,third-party Applications
18,11,,,Dave Genesy,Head of office,,
14,9,,,David Genesy,Library Director,,
22,14,,,Andres Espinoza, Manager Commanding Officer,,
  1. (完成!)需要更新列名。姓名格式:姓名首字母大写,其他字母小写。

  2. (完成!)需要使用域@abc.Email 格式更新列电子邮件:姓名和完整姓氏的第一个字母,小写

  3. (未完成)具有相同 ID 的电子邮件应包含数字。示例:姓名 Max Houston,电子邮件 mhouston1@examples.com 等。

#!/bin/bash
inputfile="accounts.csv"
echo "id,location_id,organization_id,service_id,name,title,email,department" > accounts_new.csv
while IFS="," read -r rec_column1 rec_column2 rec_column3 rec_column4 rec_column5 rec_column6 rec_column7 rec_column8
do
   surnametemp="${rec_column5:0:1}$(echo $rec_column5 | awk '{print $2}')"
   namesurname=$(echo $rec_column5 | sed 's! .!\U&!g')
   echo $rec_column1","$rec_column2","$rec_column3","$rec_column4","$namesurname","$rec_column6",""${surnametemp,,}@abc.com"","$rec_column8 >>accounts_new.csv
done < <(tail -n +2 $inputfile)

怎么做?

输出文件

id,location_id,organization_id,service_id,name,title,email,department
14,9,,,Dave Genesy,Library Director,dgenesy@abc.com,
14,9,,,David Genesy,Library Director,dgenesy2@abc.com,
15,9,,,maria Kramer,Library Divisions Manager,mkramer@abc.com,
26,18,,,Sharon Petersen,Administrator,spetersen@abc.com,
27,19,,,Shen Petersen,Administrator,spetersen2@abc.com,

【问题讨论】:

  • 欢迎来到 SO 并特别感谢您在您的问题中付出的努力,继续努力。您能否在您的问题中发布预期输出的示例(请不要在 cmets 中)以使问题更加清晰。
  • 添加结果,修复“经理,指挥官”

标签: bash csv awk


【解决方案1】:

任务规范

如果另有说明,这项任务会容易得多:

  1. 为每封电子邮件添加电子邮件迭代器 或
  2. 将电子邮件迭代器添加到第二次、第三次……发生

但它被指定: 如果电子邮件被多次使用,则将电子邮件迭代器添加到每封电子邮件。

此规范需要通过行进行两次迭代,因此使这项任务更加困难。

正确的工具

我的经验法则是:对简单任务使用纯 bash 工具(grep、sed 等),对中等任务使用 awk,对复杂任务使用 python。在这种情况下(对行进行两次迭代)我会使用 python。但是问题规范中没有python标签,所以我使用了awk。

解决方案

<accounts.csv \
gawk -vFPAT='[^,]*|"[^"]*"' \
'
BEGIN { 
  OFS = "," 
}; 
{ 
  if ($7 == "") { 
    split($5,name," "); 
    firstname = substr(tolower(name[1]),1,1); 
    lastname = tolower(name[2]); 
    domain="@abc.com"; 
    $7=firstname "." lastname domain;
  }; 
  emailcounts[$7]++; 
  immutables[++iter]=$1","$2","$3","$4","$5","$6","$8; 
  emails[iter]=$7;
} 
END { 
  for (iter in immutables) {
    if (emailcounts[emails[iter]] > 1) {
      emailiter[emails[iter]]++; 
      email=gensub(/@/, emailiter[emails[iter]]"@", "g", emails[iter]);
    } else {
      email=emails[iter]
    }; 
    print immutables[iter], email
  }
}'

结果

id,location_id,organization_id,service_id,name,title,department,email
36,,,22,Joe Smith,third-party,third-party Applications,john.smith@example.org
18,11,,,Dave Genesy,Head of office,,d.genesy1@abc.com
14,9,,,David Genesy,Library Director,,d.genesy2@abc.com
22,14,,,Andres Espinoza,"Manager, Commanding Officer",,a.espinoza@abc.com

说明

  • -vFPAT='[^,]*|"[^"]*"'读取csv
  • $7=firstname "." lastname domain;} 替代电子邮件字段
  • emailcounts[$7]++ 计算电子邮件发生次数
  • iter 保留顺序的迭代器
  • immutables[++iter]=$1","$2","$3","$4","$5","$6","$8 为第二个循环保存非电子邮件字段
  • emails[iter]=$7 为第二个循环保存电子邮件
  • for (iter in immutables) 遍历不可变字典中的键
  • {if (emailcounts[emails[iter]] &gt; 1)如果出现超过 1 次则更改电子邮件
  • emailiter[emails[iter]]++增加邮件迭代器
  • email=gensub(/@/, emailiter[emails[iter]]"@", "g", emails[iter]) 将迭代器添加到电子邮件
  • print immutables[iter], email打印

【讨论】:

  • 在上面的解决方案中有一个无用的cat。否则..很好解释。
  • @kvantour 同意效率。它甚至比无用更糟糕。但是,可能我个人的选择是在开始时查看我正在解析的文件是什么。
  • 在这种情况下你可以使用&lt;inputfile gawk '...' -
【解决方案2】:

输入(mailcsv)文件为:

id,location_id,organization_id,service_id,name,title,email,department
14,9,,,Dave Genesy,Library Director,dgenesy@abc.com,
14,9,,,David Genesy,Library Director,dgenesy@abc.com,
15,9,,,maria Kramer,Library Divisions Manager,mkramer@abc.com,
26,18,,,Sharon Petersen,Administrator,spetersen@abc.com,
27,19,,,Shen Petersen,Administrator,spetersen2@abc.com,

你可以使用awk等等:

awk -F, ' NR>1 { mails[$7]+=1;if ( mails[$7] > 1 ) { OFS=",";split($7,mail1,"@");$7=mail1[1]mails[$7]"@"mail1[2] } else { $0=$0 } }1' mailscsv

将字段分隔符设置为 ,然后创建一个以电子邮件地址为键的数组。每次遇到电子邮件地址时增加索引。如果该地址不止一次出现,则将该地址拆分为另一个基于“@”的数组 mail1。将 $7 设置为数组 mail1 的第一个索引(@ 之前的电子邮件地址),然后是电子邮件地址的 mails 索引的值,然后是“@”和 mail1 的第二个索引(@ 之后的部分)如果只有一次出现电子邮件地址的简单设置整行。使用 1 打印该行。

【讨论】:

  • 添加索引的字符串中没有逗号。
  • 添加索引的数组中没有逗号。 15,9,,,maria Kramer,图书馆部门经理,mkramer@abc.com, 16 10 Dave Genesy 测试员 dgenesy2@abc.com 17 10 Maria Kramer 图书馆部门经理 mkramer2@abc.com 18 11 Dave Genesy 办公室主任 dgenesy3@ abc.com 19,11,,, Elizabeth Meeks, 分公司经理,emeeks@abc.com,
  • 15,9,,,maria Kramer,Library Divisions Manager,mkramer@abc.com, 16 10 Dave Genesy tester dgenesy2@abc.com 17 10 Maria Kramer Library Division Manager mkramer2@abc.com 18 11 Dave Genesy Head of office dgenesy3@abc.com 19,11,,,Elizabeth Meeks,Branch Manager,emeeks@abc.com,
  • 我必须将输出字段分隔符 (OFS) 添加为 ;我已经修改了答案
猜你喜欢
  • 2014-04-21
  • 2014-10-22
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
相关资源
最近更新 更多