如何根据搜索模式从大型 .txt 文件中提取特定行

如何根据搜索模式从大型 .txt 文件中提取特定行

我使用的是 Windows 7 64 位

我有一个很大的 .txt 文件(800 mb 以上),包含以下格式

文件以空格分隔

8232394 06774483 N 19850910 19870818 19910818 EXP. 
8309716 06774483 N 19850910 19870818 19910319 REM.
4687262 06908244 N 19860917 19870818 19990815 EXP. 
4687262 06908244 N 19860917 19870818 19990309 REM. 
4687262 06908244 N 19860917 19870818 19950221 M184 
4687262 06908244 N 19860917 19870818 19910108 M173 
4687262 06908244 N 19860917 19870818 19880802 ASPN 
4687263 06868897 N 19860527 19870818 19990128 M185
4687263 06868897 N 19860527 19870818 19950509 RMPN
4687263 06868897 N 19860527 19870818 19950509 ASPN 
4687263 06868897 N 19860527 19870818 19950119 M184 
4687263 06868897 N 19860527 19870818 19910311 ASPN 
4687263 06868897 N 19860527 19870818 19910124 M173 
4687264 06882047 N 19860703 19870818 19990815 EXP. 
4687264 06882047 N 19860703 19870818 19990309 REM. 
4687264 06882047 N 19860703 19870818 19950503 RMPN 
4687264 06882047 N 19860703 19870818 19950503 ASPN 
4687264 06882047 N 19860703 19870818 19950119 M184 
4687264 06882047 N 19860703 19870818 19910311 ASPN 
RE45781 14176526 N 20140210 20151027 20150929 ASPN 
RE45786 14260890 N 20140424 20151027 20150929 ASPN 
RE45790 14454285 Y 20140807 20151103 20151008 ASPN 
RE45793 13445791 N 20120412 20151103 20151006 ASPN 

我有另一个 .txt 文件(小),包含以下格式

4687264 
4687264 
4687264 
RE45781 
RE45786 
RE45790 
RE45793 

现在我想从大文件中提取与小文件匹配的行,相对于第 1 列,该行仅包含小 txt 文件中存在的行

结果文件应如下所示

4687264 06882047 N 19860703 19870818 19990815 EXP. 
4687264 06882047 N 19860703 19870818 19990309 REM. 
4687264 06882047 N 19860703 19870818 19950503 RMPN 
4687264 06882047 N 19860703 19870818 19950503 ASPN 
4687264 06882047 N 19860703 19870818 19950119 M184 
4687264 06882047 N 19860703 19870818 19910311 ASPN 
RE45781 14176526 N 20140210 20151027 20150929 ASPN 
RE45786 14260890 N 20140424 20151027 20150929 ASPN 
RE45790 14454285 Y 20140807 20151103 20151008 ASPN 
RE45793 13445791 N 20120412 20151103 20151006 ASPN 

有什么办法吗?

我最初将其发布在 vim 通用论坛上,因为我发现 vim 能够打开大文本,但我认为这个论坛更大,因为它也可以使用其他程序来完成。

VIM 论坛

答案1

格鲁普

使用 GNU grep 你可以这样做

$ grep -f small_list.txt big_file.txt
4687264 06882047 N 19860703 19870818 19990815 EXP.
4687264 06882047 N 19860703 19870818 19990309 REM.
4687264 06882047 N 19860703 19870818 19950503 RMPN
4687264 06882047 N 19860703 19870818 19950503 ASPN
4687264 06882047 N 19860703 19870818 19950119 M184
4687264 06882047 N 19860703 19870818 19910311 ASPN
RE45781 14176526 N 20140210 20151027 20150929 ASPN
RE45786 14260890 N 20140424 20151027 20150929 ASPN
RE45790 14454285 Y 20140807 20151103 20151008 ASPN
RE45793 13445791 N 20120412 20151103 20151006 ASPN

(剪切并粘贴您的精确数据后在 Linux 上进行测试)

如果您愿意并且能够安装和使用 vim,grep 应该没有问题。

查找字符串

你也可以用本机findstr

C:> findstr /G:small_list.txt big_file.txt
4687264 06882047 N 19860703 19870818 19990815 EXP.
4687264 06882047 N 19860703 19870818 19990309 REM.
4687264 06882047 N 19860703 19870818 19950503 RMPN
4687264 06882047 N 19860703 19870818 19950503 ASPN
4687264 06882047 N 19860703 19870818 19950119 M184
4687264 06882047 N 19860703 19870818 19910311 ASPN
RE45781 14176526 N 20140210 20151027 20150929 ASPN
RE45786 14260890 N 20140424 20151027 20150929 ASPN
RE45790 14454285 Y 20140807 20151103 20151008 ASPN
RE45793 13445791 N 20120412 20151103 20151006 ASPN

我之所以grep首先提到这一点只是出于习惯,而且是因为我经常忘记它findstr并不像我以前认为的那么愚蠢。

警告

我很确定 grep 处理非常大的文件不会有问题。我不太确定 findstr 是否可行,但我想不出任何理由不去尝试一下。


附录:

常用表达

grep和都findstr可以找到固定字符串,但它们也可以与常用表达

如果要在每行的第一个单词中查找这些字符串,则可以在字符串前面加上插入符号,^以指示要查找的字符串必须位于行的开头。

^4687264 
^RE45781 
^RE45786 
^RE45790 
^RE45793 

您可以在vim中使用:%s/^/^/- 您也可以使用 sed、awk、perl 等来轻松编辑搜索字符串文件。请注意,^搜索表达式(替代)命令的一部分s是元字符,表示“行首”。第二个^是在替换字符串部分,它表示文字字符^

如果我不想编辑要找到的字符串文件,我会做类似的事情

sed -e 's/^/^/' < small_list.txt > temp.txt; grep -f temp.txt big_file.txt; rm temp.txt

grep假设使用正则表达式。findstr您需要将/R选项添加到命令中(未经测试)。

答案2

电源外壳

不知道运行时性能,但 powershell 在所有当前 Windows 操作系统上都默认安装。

$small = (gc small.txt | group).Name
gc large.txt | ? {$small -contains $_.Split(" ")[0]}

分解

$small = (gc small.txt | group).Name
 - Get-Content of small.txt
 - Group the content to retain a list of unique values as to speed up the search
 - Store in $small variable

gc large.txt | ? {$small -contains $_.Split(" ")[0]}
 - Get-Content of large.txt
 - ? => where clause
   - $_ contains a complete line from large.txt. 
     Split it up by spaces and just select the first element of that result
   - Search the first element in the $small list

相关内容