我有大约 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,否则只会有一个输出文件,而不是每个日期一个,这不是我想要的行为。
这将扩展另一个解决方案,为您提供一个字符串文件名,将其附加到原始文件名加上MMDDYYYY
或YYYYMMDD
甚至可能是匹配字符串的任意组合或单个字符YYYY
,MM
或DD
部分,以附加到每个文件中找到的那些字符串的文件名中 - 正如您所解释的那样。
基本上,您只需相应地设置变量,保存为批处理脚本 [.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