簡體   English   中英

基於一列中的模式匹配來匹配兩個CSV

[英]Match Two CSVs Based on Pattern Matching in One Column

我有以下格式的兩個CSV文件:

==

FirstName | LastName | Email
Steven | Smith | stevesmith1@gmail.com
Jane | Brown | jb155@yahoo.com
Paul | Gibson | paulgibbs@outlook.com

==

ID | FirstName | LastName | IncompleteEmail
1028332982 | Steven | Smith | s*****1@g*l.com
1028820233 | Jane | Brown | j******n@yahoo.com
934943823 | Paul | Gibson | p*****s@h****l.com

==

我想以此為基礎在兩個CSV文件之間進行匹配-如果FirstNameLastName相同,則第一個CSV中的Email與第二個CSV中IncompleteEmail的模式匹配,應創建包含ID | Email的輸出ID | Email ID | Email

在上面的示例中,輸出如下所示:

ID | Email
1028332982 | stevesmith1@gmail.com

其原因是因為兩個CSV中的“ Steve”和“ Smith”相同,並且IncompleteEmail模式與Email匹配。 其他輸入不匹配,因為IncompleteEmail模式與電子郵件不匹配。

我以前使用的join腳本(如join -i -t '|' -j 1 -o 2.2,2.3 1.txt 2.txt > out.txt )來處理類似的文件,但我不知道怎么修改連接腳本以使用模式而不是完全匹配。 我知道AWK可能會采用類似的方法,但我願意接受建議。

需要一些可以處理大量輸入的東西(兩個CSV,每個CSV超過1000萬行)。

提前致謝。

假設您希望*的任何重復都以與.*正則表達式中的處理方式相同,而每個其他RE元字符(例如. )都按字面處理,並且^不能出現在電子郵件地址中:

$ cat tst.awk
BEGIN { FS=" [|] "; OFS=" | " }
FNR==1 {
    for (i=1; i<=NF; i++) {
        f[$i] = i
    }
}
{ name = $(f["FirstName"]) FS $(f["LastName"]) }
NR==FNR {
    name2fullEmail[name] = $(f["Email"])
    next
}
FNR==1 {
    print "ID", "Email"
    next
}
name in name2fullEmail {
    fullEmail = name2fullEmail[name]
    partEmail = $(f["IncompleteEmail"])
    gsub(/./,"[&]",partEmail)
    gsub(/[[][*][]]/,".*",partEmail)
    if (fullEmail ~ "^"partEmail"$") {
        print $(f["ID"]), fullEmail
    }
}

$ awk -f tst.awk file1 file2
ID | Email
1028332982 | stevesmith1@gmail.com

我認為您的第一個csv文件為df1 ,而第二個csvdf2 因此,您可以嘗試以下操作:

import pandas as pd
import re

df_new = pd.merge(df1,df2, on=['FirstName','LastName'], how='inner')
mails = []
regex = "((\w{1})\D.*(\w{1}\@\w{1})\D.*(\w{1}[\.]\D.+)"
for d in range(len(df_new)):
    inmail = re.findall(regex,df_new.iloc[d]["IncompleteEmail"])
    commail = re.findall(regex,df_new.iloc[d]["Email"])
    if inmail == commail:
        mails.append([df_new.iloc[d]['ID'],df_new.iloc[d]["Email"]])
pd.DataFrame(mails, columns=["ID","Email"])

輸出:

           ID                  Email
0  1028332982  stevesmith1@gmail.com

另一個問題:

$ awk -F" [|] " -v OFS="|" '   # set field separators
NR==FNR {                      # process first file
    a[$1 OFS $2]=$3            # hash email, use name as key
    next
}
((i=$2 OFS $3) in a) {         # process second file
    gsub(/\./,"\\.",$4)        # escaping:      . -> \.
    gsub(/\*+/,".*",$4)        #           *{1,n} -> .*
    if(FNR==1 || a[i]~$4)      # if header record or regex match
        print $1,a[i]          # then output
}' file1 file2                 # mind the order

輸出:

ID|Email
1028332982|stevesmith1@gmail.com

而處理所述第二文件file2 gsub(/\\*+/,".*",$4)試圖使電子郵件的正則表達式ISH: s*****1@g*l.com - > s.*1@g.*l\\.com 提供的樣本數據除*和之外沒有其他正則表達式元字符. 但是其他人(例如+ )也應該避免使用虛假匹配,以避免誤匹配,但是我不確定您是否像*一樣對他們有特殊的含義。

另外,它不會容忍file1重復名稱。 最后的勝利。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM