如何在awk中从文件读取正则匹配字符串并拆分大文件
按匹配规则拆分大文件到对应命名的小文件
问题背景
我需要把一个大文件拆分成多个小文件,要求大文件中包含指定匹配字符串的行,存入和该匹配字符串同名的文件里。单个匹配的话我知道用awk可以实现,比如:
awk '/apple/{print}' large_file.txt > apple.txt
现在想写个脚本,从另一个文件里读取所有正则匹配字符串,然后把对应行存入对应文件,怎么用awk实现?
假设匹配字符串存在matching_string.txt里,内容是:
apple orange mango
large_file.txt的示例内容:
apple is a great fruit we should eat apple orange is juicy mango is the king of fruits litchi is a seasonal fruit
预期生成apple.txt、orange.txt、mango.txt三个文件,分别存入各自匹配的行。我是Linux新手,脚本水平入门,也接受正则、sed、Python这类其他解决方案。
解决方案
方法1:单趟awk处理(高效,适合大文件)
这个方法只需要读取一次大文件,处理大文件时效率更高,避免重复IO操作:
awk ' BEGIN { # 先读取匹配规则文件,将每个规则存入数组 while ((getline pat < "matching_string.txt") > 0) { patterns[pat] = 1 } close("matching_string.txt") } # 遍历大文件的每一行 { # 检查当前行匹配哪个规则 for (pat in patterns) { if ($0 ~ pat) { # 将行写入对应命名的文件 print > (pat ".txt") # 若一行可能匹配多个规则,需要去掉下面的break;仅匹配第一个规则则保留 break } } } ' large_file.txt
方法2:tcsh脚本(逻辑直观,适合新手理解)
你已经调整出适配tcsh的可用脚本,整理如下:
#!/bin/tcsh -f foreach word ("`cat matching_string.txt`") # 若目标文件已存在,先删除 if (-r ${word}.txt) then rm -rf ${word}.txt endif # 调用awk提取匹配行并写入对应文件 awk "/${word}/ { print }" large_file.txt > ${word}.txt end
注意:该脚本会循环调用awk,每处理一个规则就读取一次大文件,大文件体积较大时效率偏低。
方法3:Python脚本(易读易懂,跨平台)
如果熟悉Python,这个写法更直观,也方便后续扩展正则匹配:
# 读取匹配规则,过滤空行 with open('matching_string.txt', 'r') as f: patterns = [line.strip() for line in f if line.strip()] # 提前打开所有输出文件的句柄 file_handles = {} for pat in patterns: file_handles[pat] = open(f'{pat}.txt', 'w') # 遍历大文件,将匹配行写入对应文件 with open('large_file.txt', 'r') as f: for line in f: line_content = line.rstrip('\n') for pat in patterns: # 简单字符串匹配,如需正则匹配请替换为re.search(pat, line_content) if pat in line_content: file_handles[pat].write(line_content + '\n') # 一行匹配多个规则则删除break,仅匹配第一个则保留 break # 关闭所有文件句柄 for fh in file_handles.values(): fh.close()
若需要正则匹配,只需在开头导入re模块,将if pat in line_content替换为if re.search(pat, line_content)即可。
内容的提问来源于stack exchange,提问作者Aditya
相关产品推荐
相关产品推荐

