基于列Windows的大文件过滤拆分

Jay*_*Jay 2 windows grep awk

我有大约 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
Run Code Online (Sandbox Code Playgroud)

我想删除某些日期。例如,我可能想为 12/20/2015 和 12/22/2015 生成文件。

12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
Run Code Online (Sandbox Code Playgroud)

12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
Run Code Online (Sandbox Code Playgroud)

我可以很容易地使用grep做到这一点,在linux做grep '12/20/2015' filein > fileout20grep '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
Run Code Online (Sandbox Code Playgroud)

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

Vom*_*yle 5

我不想多次遍历每个输入文件。

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

哦,你为什么不从 LOOP 中说没有迭代!!. . .

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
}
Run Code Online (Sandbox Code Playgroud)

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


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

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

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

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

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

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

(我会保留下面的批处理脚本解决方案,以防任何人都觉得它有用。)


我想删除某些日期。例如,我可能想为 12/20/2015 和 12/22/2015 生成文件。

评论

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

这将扩大对其他的解决办法给你一个字符串文件名添加到原始文件名加上MMDDYYYY或者YYYYMMDD甚至可能的任何组合或单个字符YYYYMMDD匹配的字符串的一部分追加到这些文件名每个文件找到的字符串——正如你所解释的。

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

批处理脚本变量说明

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

  • SET StringList=值将是一个完整的路径位置和文件名,您将保存为文本文件,每个串(即12/20/201512/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
Run Code Online (Sandbox Code Playgroud)

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

12/15/2015
12/22/2015
12/23/2015
12/24/2015
Run Code Online (Sandbox Code Playgroud)