我需要根据给定的模式(在本例中为电子邮件地址)合并2个文件 如果可能的话,我想用grep / sed来做这个。请解释答案,以便我的弱脑能够处理它。
新信息:没有Field Map。这些文件来自2个不同的数据源,并且行数并不总是相同。这是现实世界:当Bob停止更新他的博物馆会员资格时,他将不再列在文件2中。这是关于大型非营利组织会员身份的每周报告的一部分。文件1将一直增长到年底,文件2可能会缩小或增长。
我已将第二个文件设置为始终以逗号分隔的位置,并且第一个字段将始终为电子邮件地址,如文件1中所示。
在文件1中有一行如下:
007@some.org,007,/Members/Inactive/Delete,2013-06-07T04:41:56.000Z,Never
在文件2中,有一行如下:
User 007@some.org: Forward To:None Enabled:false Action:KEEP
我希望将文件2中的内容添加到文件1中,以创建格式为3的文件:
007@some.org,007,/Members/Inactive/Delete,2013-06-07T04:41:56.000Z,Never,Forward to:None,Enabled:false,Action:KEEP
3个新列应始终添加到该行的末尾。
答案 0 :(得分:1)
首先使用搜索和替换修改所需格式的文件2(逗号分隔)。在这里,我使用perl
来实现这一目标。 sed
也可以使用
perl -pe 's/User\s+(\S+):\s+(.*?:\S+)\s+(.*?:\S+)\s+(.*?\S+)/\1,\2,\3,\4/g' file2 > file2_new
这将导致:
$ cat file2_new
007@some.org,Forward To:None,Enabled:false,Action:KEEP
然后只需使用join
与分隔符,
连接两个文件
join -t , file1 file2_new
输出:
007@some.org,007,/Members/Inactive/Delete,2013-06-07T04:41:56.000Z,Never,Forward To:None,Enabled:false,Action:KEEP
答案 1 :(得分:1)
使用较新版本(适用于\s
和\S
代替[[:space:]]
和[^[:space:]]
)GNU awk(适用于gensub()
):
$ cat tst2.awk
BEGIN {re="\\S+\\s+([^:]+):\\s+([^:]+:\\S+)\\s+(\\S+)\\s+(\\S+).*"; FS=OFS=","}
NR==FNR {map[gensub(re,"\\1","")] = gensub(re,"\\2,\\3,\\4",""); next}
{print $0, map[$1]}
$
$ cat file1
007@some.org,007,/Members/Inactive/Delete,2013-06-07T04:41:56.000Z,Never
$
$ cat file2
User 007@some.org: Forward To:None Enabled:false Action:KEEP
$
$ awk -f tst2.awk file2 file1
007@some.org,007,/Members/Inactive/Delete,2013-06-07T04:41:56.000Z,Never,Forward To:None,Enabled:false,Action:KEEP
或任何现代的awk:
$ cat tst.awk
BEGIN{ FS=OFS="," }
NR==FNR {
email = $0
gsub(/^[^[:space:]]+[[:space:]]+|:.*/,"",email)
sub(/^[^:]+:[[:space:]]*/,"")
rec = ""
while ( match($0,/[^:]+:[^:[:space:]]+/) > 0 ) {
rec = rec (rec ? OFS : "") substr($0,RSTART,RLENGTH)
$0 = substr($0,RSTART+RLENGTH+1)
sub(/^[[:space:]]+/,"",$0)
}
map[email] = rec
next
}
{ print $0, map[$1] }
$
$ cat file1
007@some.org,007,/Members/Inactive/Delete,2013-06-07T04:41:56.000Z,Never
$
$ cat file2
User 007@some.org: Forward To:None Enabled:false Action:KEEP
$
$ awk -f tst.awk file2 file1
007@some.org,007,/Members/Inactive/Delete,2013-06-07T04:41:56.000Z,Never,Forward To:None,Enabled:false,Action:KEEP
答案 2 :(得分:0)
我以前建议加入评论而不注意输入和输出格式。正如EdMorton指出的那样,即使输入文件已经排序,也不能单独在连接中完成。所以经过与EdMorton的一些讨论,我实际上详细地解决了这个问题,这是我目前的解决方案,假设第二个文件是TAB分离的:
sed -re 's/^User\s//' -e 's/:/,/' file2 | join -t , file1 - | sed -re 's/\t/,/g' -e 's/,,/,/'
以上命令在我的cygwin / win7环境下工作,如果你的shell或file2分隔符不同,你可能需要稍微玩一下。
一些解释:
sed -re 's/^User\s//' -e 's/:/,/' file2
删除前导“user”并将冒号的第一个匹配项更改为逗号,这使得file2可以使用逗号分隔符与file2连接。
sed -re 's/\t/,/g' -e 's/,,/,/'
根据最终格式的要求,用逗号替换分隔符。因为join会在file1和file2之间的输出中添加一个分隔符,所以我们会看到一对没有最后替换的逗号。
这是输出: