我在文件1中有一个电子邮件地址列表,我正在尝试在文件2中查找这些电子邮件地址(来自文件1)。如果电子邮件地址在文件2中,我希望它返回上面的行,这是他们的用户名。例如:
这是文件1:
test@test.com
bob@test.com
sally@test.com
eve@test.com
这是文件2:
testing
test@test.com
robert
bob@test.com
sally
sally@test.com
eve92
eve@test.com
我希望输出为:
testing
robert
sally
eve92
我正在调查awk
,但似乎无法弄明白。有关如何最好地做到这一点的任何想法?愿意通过bash或python或者你认为最好的方式来做。谢谢!
答案 0 :(得分:2)
这是实现您想要的强大而有效的方式:
$ awk 'NR==FNR{a[$1];next} NR%2{prev=$0;next} $1 in a{print prev}' file1 file2
testing
robert
sally
eve92
它从电子邮件地址中删除前导/尾随空白,对两个文件中的整个电子邮件地址进行字符串(而不是正则表达式)匹配,并且仅将电子邮件地址与文件2的每个第2行进行比较,因此没有机会错误匹配,错过真正匹配的可能性为零。
答案 1 :(得分:0)
假设列表无序且file2不是太大,为第二个文件构建字典似乎是一个不错的选择:
users = {}
with open("file2") as file2:
try:
email = "" # initialize
while True:
while "@" not in email:
username = email
email = file2.next().strip()
users[email] = username
email = ""
username = ""
except StopIteration:
pass
print users
result = []
with open("file1") as file1:
try:
for line in file1:
result.append(users[line.strip()])
except StopIteration:
pass
result
将包含O(m+n)
时间和O(m)
空间的用户名列表(对于file2的字典)
答案 2 :(得分:0)
这应该有效:grep -B1 -F -f file1 file2
-B1:比赛前获得1行(GNU grep)
-F:固定字符串匹配,而不是正则表达式
-f:在case中加载来自file = file1的模式
file2:要应用grep并获取上一行(B1)的文件
更新:
经过一些测试,这个解决方案有一个bug:grep返回两行
匹配模式的一行=电子邮件
模式匹配前的另一行=用户名。
由于-B1 grep运算符,模式匹配前的行首先出现。
只获取第一行=用户名而不是获得模式匹配(第二行)的简单方法是:
grep -B1 -F -f file1 file2 |grep -v "@"
考虑到用户名不包括" @" 。
答案 3 :(得分:0)
首先使用file2中的所有前一行创建一个数组
第一步的每个命令都以next
结束
现在解析file1(NR
将大于FNR
)并在数组中查找它们。
awk 'NR==FNR{a[$1]=x;x=$0;next} $1 in a{print a[$1]}' file2 file1
答案 4 :(得分:0)
@Neemaximo:试试:
awk 'FNR==NR{if($0 !~ /\.com/){A[++i]=$0;next};B[$0];next} ($0 in B){print A[++q]}' file2 file1
OR
awk 'FNR==NR{if($0 !~ /\.com/){A[++i]=$0;next};B[$0]=A[i];;next} ($0 in B){print B[$0]}' file2 file1
考虑您的Input_files仅与每个显示的样本相同。所以上面的解决方案检查FNR == NR条件,只有在读取第一个名为file2的文件时才会为TRUE,这样它将检查一行是否不等于.com然后它创建一个带有变量I的数组A的数组项,其值为是当前行,然后它创建一个数组B,其值为当前行(并且它不等于.com)到数组A的索引为变量I的值,接下来将避免执行所有其他语句。 现在检查何时读取名为file1的第二个文件,检查数组B中是否存在当前行,然后打印数组B的值。
答案 5 :(得分:0)
如果电子邮件是唯一的(可以肯定的话),您可以使用文件2构建一个数组,然后使用文件1对其进行索引:
$ awk 'NR==FNR{getline l; arr[l]=$1; next} $1 in arr {print arr[$1]}' f2 f1
testing
robert
sally
eve92
在Python中,您可以这样做:
with open("f2") as f2:
keys=[(next(f2).strip(), k.strip()) for k in f2]
with open("f1") as f1:
emails=[e.strip() for e in f1]
for e in emails:
for t in keys:
if t[0]==e:
print t[1]
支持重复条目。如果您知道自己的电子邮件地址是唯一的,那么效率会更高:
with open("f2") as f2:
keys={next(f2).strip(): k.strip() for k in f2}
with open("f1") as f1:
for e in f1:
e=e.strip()
print keys.get(e, "{} not found".format(e))
这与awk
计划基本相同。