2008-11-29 38 views
2

我有一个n行的文件。 (n大于1亿)批处理文件保留十行之一

我想输出一个只有10行中有1行的文件,我不能将文件分成十部分,只保留一部分,因为它必须更随机一点。后来我必须做一个统计分析,我不能在数据中产生强烈的偏见)。

我想读取文件和每个记录,如果记录号码mod 10然后输出它。

约束条件是:

  • 它是一个窗口(可能硬化)的计算机可能XP Vista或Windows Server 2003

  • 没有开发工具可用

  • 没有网络,USB,光盘。不要读取外部通信。

因此我在想windows批处理文件(我不能假设powershell,并且vbscript很可能已被删除)。目前正在查看FOR/F命令。 但我不是专家,我不知道如何做到这一点。

谢谢Paul的回答。 我重新格式化(与胡沙姆帮助)的答案,把它放在一个批处理文件:

@echo off 
setlocal 
findstr/N . inputFile| findstr ^[0-9]*0: >temporaryFile 
FOR /F "tokens=1,* delims=: " %%i in (temporaryfile) do echo %%j > outputFile 

感谢QUUX和大同为同类替代解决方案。然而,在对较大文件进行快速测试之后,Paul的答案大约快了8倍。我猜测(在SET中)的评估是缓慢的,即使逻辑看起来很棒。

+0

那些是什么样的限制?在这些限制下,你不能从事专业工作。听起来对我来说很可疑。 – 2008-11-29 13:07:45

+0

这将教我重新键入它,而不是剪切和粘贴什么工作:) – 2008-11-29 13:34:40

回答

6

好吧,我想我已经破解了:

findstr/N . path-to-log-file | findstr ^[0-9]*0: 

(使用FINDSTR行号添加到该行的开头,然后再只打印线在零结尾的行号)

所以你会得到10一条线,而是用行号和结肠前置到各行

如果我可以只使用剥说出来的命令行工具,想办法,我我会编辑这个答案:)

FOR /F "tokens=1,2* delims=: " %i in (file-with-linenumbers) do echo %j 

保罗删除的行号和结肠。

+0

两个快速的东西:@回声之前输出只是数据,而令牌是1,*。除此之外,它是伟大的,再次感谢 – 2008-11-29 13:36:53

2

这里有一个小小的命令脚本,它可以完成你想要的任务(精确地每10行文件中输出lines32.txt)。该文件(我的测试)至32包容性,每行举行的1号,输出功率为10,20,30

@echo off 
setlocal 

set /a "n = 0" 
for /f %%i in (lines32.txt) do call :fn %%i 
endlocal 
goto :eof 

:fn 
set /a "n = n + 1" 
if not %n%==10 goto :eof 
echo %1 
set /a "n = 0" 
goto :eof 

,因为坏的旧DOS的Windows命令语言已经相当方式天。我仍然不认为这是ksh或bash的匹配,但它确实是一份体面的工作。

+0

2变化,它也工作,如果有线的空间; ... call:fn“%% i” and echo%〜1 – wimh 2008-11-29 13:44:29

1

保罗有一个非常好的答案。通过添加重定向操作符,您可以将数据写入文件。

findstr /n . yourLogFile.txt | findstr ^[0-9]*0: > numberedFile.txt 
for /f "tokens=1,2* delims=:" %i in (numberedFile.txt) do echo %j > smallFile.txt 
del numberedFile.txt 

这将工作,如果从命令行运行。如果你想把它放在一个批处理文件中,用'%%'替换每个'%'字符(这样%i将变成%% i,而%j将变成%% j,因为在批处理文件中'%'有一个特殊的含义)。

1

所选答案可能需要很长时间才能处理,因为它必须处理整个文件两次。如果该文件是数百万行... woosh。

这是我想出来的。它只是迈着沿处理文件顺序,打印每10号线(在你最喜欢的数字结尾):

@ECHO OFF 
SETLOCAL 
SET lastdigit=7 
SET linecounter=0 
FOR /F "tokens=*" %%a IN (text.txt) DO CALL :picker %%a 
ENDLOCAL 
GOTO :eof 

:picker 
set line=%* 
IF {%linecounter:~-1%} == {%lastdigit%} ECHO %linecounter% %line% 
SET /a linecounter=%linecounter% + 1 
GOTO :eof 

每一行的编号,从零开始。其中%linenumber%以%lastdigit%结尾的任何行都会与控制台一起回显,同时还会显示linenumber。使用set /?看看我是怎么想出这个 {%linecounter:〜-1%}的东西(它只是除去最后一个数字的数字)。