Golang中如何提取包含常见邮箱的行

Golang中如何提取包含常见邮箱的行 你好,我是Go语言的新手。我想过滤我拥有的两个文件。第一个文件包含电子邮件列表(大约200万条),第二个文件包含邮箱:哈希值(大约50万条)。我想逐行比较这两个文件,如果第二个文件中的邮箱存在于第一个文件中,那么我想将该邮箱:哈希值导出到第三个文件中。例如:

first.txt

testemail@test.com
test@gmail.com
test@yahoo.com
test@outlook.com
test@live.com

second.txt

test@yahoo.com:53534535$5435345
test@outlook.com:23534535$5864345
test1@outlook.com:23534535$586745
test5@outlook.com:23534535$5864345

它应该输出一个包含以下内容的第三个文件:

test@yahoo.com:53534535$5435345
test@outlook.com:23534535$5864345

这些是存在于第一个文件中的邮箱。


更多关于Golang中如何提取包含常见邮箱的行的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

你好,它们是无序的。

更多关于Golang中如何提取包含常见邮箱的行的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


@Metalymph 谢谢伙计。你真是救星。

你好!这两个文件是有序的吗?(至少第二个是?)据我所见:不是。对吗?

Go Playground - Go 编程语言

我的解决方案,试试看。编译并运行,为其提供邮件文件、邮件与哈希文件以及输出文件的路径。

嗯,有多种方法可以实现:

  1. 首先处理文件2,创建一个以电子邮件地址为键的字典。
  2. 将此字典传递给一个读取文件1并在映射中搜索当前行的例程。如果找到,则将其写入第三个文件。

你可以使用 goroutine 和 channel。

func main() {
    fmt.Println("hello world")
}
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	// 读取第一个文件(邮箱列表)到map中,便于快速查找
	emailSet := make(map[string]bool)
	
	// 打开第一个文件
	file1, err := os.Open("first.txt")
	if err != nil {
		panic(err)
	}
	defer file1.Close()
	
	// 逐行读取第一个文件
	scanner1 := bufio.NewScanner(file1)
	for scanner1.Scan() {
		email := strings.TrimSpace(scanner1.Text())
		if email != "" {
			emailSet[email] = true
		}
	}
	
	if err := scanner1.Err(); err != nil {
		panic(err)
	}
	
	// 打开第二个文件
	file2, err := os.Open("second.txt")
	if err != nil {
		panic(err)
	}
	defer file2.Close()
	
	// 创建第三个输出文件
	file3, err := os.Create("third.txt")
	if err != nil {
		panic(err)
	}
	defer file3.Close()
	
	writer := bufio.NewWriter(file3)
	defer writer.Flush()
	
	// 逐行读取第二个文件
	scanner2 := bufio.NewScanner(file2)
	for scanner2.Scan() {
		line := strings.TrimSpace(scanner2.Text())
		if line == "" {
			continue
		}
		
		// 分割邮箱和哈希值
		parts := strings.SplitN(line, ":", 2)
		if len(parts) != 2 {
			continue
		}
		
		email := parts[0]
		
		// 检查邮箱是否存在于第一个文件中
		if emailSet[email] {
			// 写入到第三个文件
			_, err := writer.WriteString(line + "\n")
			if err != nil {
				panic(err)
			}
		}
	}
	
	if err := scanner2.Err(); err != nil {
		panic(err)
	}
	
	fmt.Println("处理完成!结果已保存到 third.txt")
}

对于大数据量处理,这里提供一个优化版本,使用更高效的内存管理:

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	// 使用更节省内存的方式处理大文件
	emailSet := make(map[string]struct{})
	
	// 处理第一个文件
	processFile("first.txt", func(line string) {
		email := strings.TrimSpace(line)
		if email != "" {
			emailSet[email] = struct{}{}
		}
	})
	
	// 处理第二个文件并输出到第三个文件
	file3, err := os.Create("third.txt")
	if err != nil {
		panic(err)
	}
	defer file3.Close()
	
	writer := bufio.NewWriter(file3)
	defer writer.Flush()
	
	processFile("second.txt", func(line string) {
		line = strings.TrimSpace(line)
		if line == "" {
			return
		}
		
		// 查找冒号位置
		colonIndex := strings.Index(line, ":")
		if colonIndex == -1 {
			return
		}
		
		email := line[:colonIndex]
		
		// 检查邮箱是否存在
		if _, exists := emailSet[email]; exists {
			writer.WriteString(line + "\n")
		}
	})
	
	fmt.Println("处理完成!")
}

func processFile(filename string, processLine func(string)) {
	file, err := os.Open(filename)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	
	scanner := bufio.NewScanner(file)
	buf := make([]byte, 0, 64*1024)
	scanner.Buffer(buf, 1024*1024)
	
	for scanner.Scan() {
		processLine(scanner.Text())
	}
	
	if err := scanner.Err(); err != nil {
		panic(err)
	}
}

这个解决方案:

  1. 使用map存储第一个文件的所有邮箱,实现O(1)时间复杂度的查找
  2. 逐行处理第二个文件,避免一次性加载大文件到内存
  3. 使用strings.SplitNstrings.Index分割邮箱和哈希值
  4. 包含错误处理和资源清理
  5. 第二个版本针对大数据量进行了优化,使用更大的缓冲区
回到顶部