基于列窗口的超大文件过滤与分割

基于列窗口的超大文件过滤与分割

我有大约 2 TB 的数据文件,格式如下

12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata

我想要提取特定日期。例如,我可能想要生成 2015 年 12 月 20 日和 2015 年 12 月 22 日的文件。

12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata

12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata

grep '12/20/2015' filein > fileout20我可以通过执行和在 Linux 中轻松使用 grep 来完成此操作,grep '12/22/2015' filein > fileout22但这有两个问题。

首先,更重要的是,它需要循环两次输入文件来生成输出。由于每个文件有 2 TB 的数据和多个日期,这是一个重大问题。(相关:我也不希望将文件分解成每个可能的日期的解决方案,因为我不需要大多数日期的数据,只需要每个输入文件中的 10% 左右)

第二个问题是我需要在 Windows 上运行它。(我意识到大多数 Linux 命令都有使用 GnuWin32 或类似程序的 Windows 等效命令,因此这不是什么大问题)

有没有什么方法可以有效地做到这一点?

编辑:到目前为止,答案有两个问题之一,所以我将稍微澄清一下。第一个问题是我不想多次遍历每个输入文件。因此,使用循环来遍历每个日期是行不通的。这是因为如果我有 200 个日期和 8000 个文件,则需要 1,600,000 次迭代。

第二个问题是我想将每个输出文件拆分成每个日期一个文件。

因此,如果有 200 个日期和 8000 个文件,应该有 1,600,000 个文件,但搜索命令只需迭代 8000 次。

编辑 2:这是一个使用 Linux 命令的解决方案。除非有人有更好的方法,否则我可能最终会使用这个

grep -f 12/20/2015 12/22/2015 filein1 > intermediate
awk -F, '{print > $1".out"}' intermediate

这是一个两阶段的过程,首先根据日期进行过滤,然后根据日期拆分结果。

答案1

我不想多次运行每个输入文件。

遍历每个日期是行不通的。我想将每个输出文件拆分为每个日期一个文件。

哦,你为什么不直接说不要从循环中进行迭代!!...

PowerShell 解决方案

(在下面的示例中相应地设置变量:字符串列表、输出文件路径,以及 MMDDYYYY 格式的字符串变量名)

Select-String -Path "C:\Path\*.txt" -Pattern 12/20/2015,12/23/2015,12/30/2015 -AllMatches | foreach-object {
   $RS = $_.Matches[0].Groups[0].Value.Replace("/","")
   $RS | Out-File "C:\Path\$RS.txt" -Append
}

(以上是一个 PowerShell 解决方案,用于根据字符串列表搜索特定目录中的所有文本文件内容。它还会将所有找到的字符串值附加到输出文件中,该输出文件具有与匹配的字符串模式匹配的有效文件名,并且该文件名对于该字符串是唯一的。)


这是使用 Linux 命令的解决方案。我可能最终会使用这个

grep -f 12/20/2015 12/22/2015 filein1 > intermediate

awk -F, '{print > $1".out"}' intermediate

这是一个两阶段的过程,首先根据日期进行过滤,然后根据日期拆分结果。

因此,您正在使用字符串列表搜索特定目录中的文本文件的文件内容。对于在每个文件中找到的每个匹配字符串,您需要将其值写入(并附加到其中,如果适用)具有“有效的”对于字符串来说文件名是唯一的——同一个文件中不存在不同的字符串。

就成为一个“更好的”方式,我认为这真的是一个意见问题,取决于你衡量的统计数据和资源。我不知道你非常担心最佳性能解决方案与你倾向于的工作方式相比。

(我将保留下面的批处理脚本解决方案,以防有人发现它有用。)


我想要提取特定日期。例如,我可能想要生成 2015 年 12 月 20 日和 2015 年 12 月 22 日的文件。

评论

但是,除非我误解了 findstr,否则只会有一个输出文件,而不是每个日期一个,这不是我想要的行为。

这将扩展另一个解决方案,为您提供一个字符串文件名,将其附加到原始文件名加上MMDDYYYYYYYYMMDD甚至可能是匹配字符串的任意组合或单个字符YYYYMMDD部分,以附加到每个文件中找到的那些字符串的文件名中 - 正如您所解释的那样。

基本上,您只需相应地设置变量,保存为批处理脚本 [.cmd],然后运行它即可。大多数变量将明确指向适用目录的特定完整路径。

批处理脚本变量说明

  • SET FilePath=值将是您要搜索的 .TXT 文件所在位置的完整路径

  • SET StringList=值将是一个完整的路径位置和文件名,您将在其中保存一个文本文件,其中包含要在文件中搜索的每个字符串(即12/20/2015,等)。您将在文件的每一行上放置一个字符串,该字符串将用作要在文件中查找的字符串12/22/2015.txt.txt(见以下示例)

  • 我将假设其他变量和其余批处理脚本逻辑都是有意义的;否则,请告诉我,我很乐意添加更多要点来澄清,等等。


批处理脚本示例

@ECHO ON

SET FilePath=C:\Path\<Location containing .TXT files to search>
SET StringList=C:\Path\DateList.txt

FOR %%A IN ("%FilePath%\*.txt") DO FOR /F "TOKENS=*" %%B IN (%StringList%) DO CALL :FindConCat "%%~B" "%%~NFXA" "%%~NA" "%%~XA"
GOTO EOF

:FindConCat
SET SearchStr=%~1
SET SearchFile=%~2
SET OutFName=%~3
SET FileExt=%~4
SET ParseStr=%SearchStr%
:::: --// MMDDYYY format
SET ParseStr=%ParseStr:~0,2%%ParseStr:~3,2%%ParseStr:~6,4%
:::: --// YYYYMMDD format
:: SET ParseStr=%ParseStr:~6,4%%ParseStr:~0,2%%ParseStr:~3,2%

FINDSTR /c:"%SearchStr%" "%SearchFile%">>"%FilePath%\%OutFName%_%ParseStr%%FileExt%"
GOTO EOF

示例字符串列表文件内容 ( SET StringList=C:\Path\DateList.txt)

12/15/2015
12/22/2015
12/23/2015
12/24/2015

答案2

使用PowerShell的一行程序:

get-content c:\filein.txt | where-object { $_ -match "12/22/2015" } | out-file c:\fileout22.txt

答案3

findstr -rc:"12/2[02]/2015" filein > fileout

相关内容