ash*_*e97 67 cygwin command split batch-file text-files
我有多个文本文件,大约有100,000行,我想将它们分成每个5000行的较小文本文件.
我用了:
split -l 5000 filename.txt
Run Code Online (Sandbox Code Playgroud)
这会创建文件:
xaa
xab
aac
xad
xbe
aaf
Run Code Online (Sandbox Code Playgroud)
没有扩展名的文件.我只想打电话给他们:
file01.txt
file02.txt
file03.txt
file04.txt
Run Code Online (Sandbox Code Playgroud)
或者如果那是不可能的,我只希望它们具有".txt"扩展名.
urs*_*san 72
我知道很久以前就已经问过这个问题了,但我很惊讶没有人给出最简单的unix答案:
split -l 5000 -d --additional-suffix=.txt $FileName file
Run Code Online (Sandbox Code Playgroud)
-l 5000
:将文件拆分为每行5,000行的文件.-d
:数字后缀.这将使后缀默认为00到99而不是aa到zz.--additional-suffix
:允许您指定后缀,此处为扩展名$FileName
:要拆分的文件的名称.file
:添加到结果文件的前缀.一如既往,请man split
查看更多详情.
对于Mac,默认版本split
显然是愚蠢的.您可以使用以下命令安装GNU版本.(有关更多GNU工具,请参阅此问题)
brew install coreutils
Run Code Online (Sandbox Code Playgroud)
然后您可以通过更换运行上面的命令split
用gsplit
.查看man gsplit
详细信息.
Ale*_*lex 20
这是C#中的一个例子(因为这就是我要搜索的内容).我需要分割一个23 GB的csv文件,大约有1.75亿行,以便能够查看文件.我把它分成每个一百万行的文件.这段代码在我的机器上大约5分钟就完成了:
var list = new List<string>();
var fileSuffix = 0;
using (var file = File.OpenRead(@"D:\Temp\file.csv"))
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
list.Add(reader.ReadLine());
if (list.Count >= 1000000)
{
File.WriteAllLines(@"D:\Temp\split" + (++fileSuffix) + ".csv", list);
list = new List<string>();
}
}
}
File.WriteAllLines(@"D:\Temp\split" + (++fileSuffix) + ".csv", list);
Run Code Online (Sandbox Code Playgroud)
Mag*_*goo 15
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET /a fcount=100
SET /a llimit=5000
SET /a lcount=%llimit%
FOR /f "usebackqdelims=" %%a IN ("%sourcedir%\q25249516.txt") DO (
CALL :select
FOR /f "tokens=1*delims==" %%b IN ('set dfile') DO IF /i "%%b"=="dfile" >>"%%c" ECHO(%%a
)
GOTO :EOF
:select
SET /a lcount+=1
IF %lcount% lss %llimit% GOTO :EOF
SET /a lcount=0
SET /a fcount+=1
SET "dfile=%sourcedir%\file%fcount:~-2%.txt"
GOTO :EOF
Run Code Online (Sandbox Code Playgroud)
这是一个应该完成任务的本机Windows批处理.
现在我不会说它会很快(每个5Kline输出文件不到2分钟)或者它不会对批量字符敏感性产生影响.真的取决于您的目标数据的特征.
我使用了一个名为q25249516.txt
100Klines数据的文件进行测试.
修订更快的版本
REM
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET /a fcount=199
SET /a llimit=5000
SET /a lcount=%llimit%
FOR /f "usebackqdelims=" %%a IN ("%sourcedir%\q25249516.txt") DO (
CALL :select
>>"%sourcedir%\file$$.txt" ECHO(%%a
)
SET /a lcount=%llimit%
:select
SET /a lcount+=1
IF %lcount% lss %llimit% GOTO :EOF
SET /a lcount=0
SET /a fcount+=1
MOVE /y "%sourcedir%\file$$.txt" "%sourcedir%\file%fcount:~-2%.txt" >NUL 2>nul
GOTO :EOF
Run Code Online (Sandbox Code Playgroud)
请注意,我使用llimit
50000进行测试.将覆盖早期的文件编号,如果llimit
*100比行的文件的数量gearter(固化通过设置fcount
到1999
和使用~3
代替~2
的文件重命名线.)
你也许可以做这样的事情 awk
awk '{outfile=sprintf("file%02d.txt",NR/5000+1);print > outfile}' yourfile
Run Code Online (Sandbox Code Playgroud)
基本上,它通过记录编号(NR)并将其除以5000来计算输出文件的名称,加1,将其整数和零填充取为2位.
默认情况下,awk
在未指定任何其他内容时打印整个输入记录.因此,print > outfile
将整个输入记录写入输出文件.
当您在Windows上运行时,您不能使用单引号,因为它不喜欢它.我认为你必须将脚本放在一个文件中,然后告诉awk
使用该文件,如下所示:
awk -f script.awk yourfile
Run Code Online (Sandbox Code Playgroud)
并且script.awk
将包含类似这样的脚本:
{outfile=sprintf("file%02d.txt",NR/5000+1);print > outfile}
Run Code Online (Sandbox Code Playgroud)
或者,如果您这样做可能会有效:
awk "{outfile=sprintf(\"file%02d.txt\",NR/5000+1);print > outfile}" yourfile
Run Code Online (Sandbox Code Playgroud)
小智 7
语法如下:
$ split [OPTION] [INPUT [PREFIX]]
Run Code Online (Sandbox Code Playgroud)
其中前缀是PREFIXaa,PREFIXab,...
只需使用正确的一个,你就完成了或只是使用mv进行重命名.我认为
$ mv * *.txt
应该工作,但首先在较小规模上测试它.
:)
小智 5
我的要求有点不同.我经常使用逗号分隔和制表符分隔的ASCII文件,其中单行是单个数据记录.而且它们非常大,所以我需要将它们分成可管理的部分(同时保留标题行).
因此,我恢复了我的经典VBScript方法,并将一个小的.vbs脚本混合在一起,该脚本可以在任何Windows计算机上运行(它由Window上的WScript.exe脚本主机引擎自动执行).
这种方法的好处是它使用Text Streams,因此底层数据不会加载到内存中(或者至少不会一次加载到内存中).结果是它非常快,并且它不需要太多内存来运行.我在i7上使用这个脚本分割的测试文件大约是1 GB的文件大小,有大约1200万行测试和25个部分文件(每个文件大约有500k行) - 处理大约需要2分钟而且没有任何时候都要使用超过3 MB的内存.
这里需要注意的是,它依赖于具有"行"的文本文件(意味着每个记录用CRLF分隔),因为文本流对象使用"ReadLine"函数一次处理一行.但是,嘿,如果你正在使用TSV或CSV文件,它是完美的.
Option Explicit
Private Const INPUT_TEXT_FILE = "c:\bigtextfile.txt" 'The full path to the big file
Private Const REPEAT_HEADER_ROW = True 'Set to True to duplicate the header row in each part file
Private Const LINES_PER_PART = 500000 'The number of lines per part file
Dim oFileSystem, oInputFile, oOutputFile, iOutputFile, iLineCounter, sHeaderLine, sLine, sFileExt, sStart
sStart = Now()
sFileExt = Right(INPUT_TEXT_FILE,Len(INPUT_TEXT_FILE)-InstrRev(INPUT_TEXT_FILE,".")+1)
iLineCounter = 0
iOutputFile = 1
Set oFileSystem = CreateObject("Scripting.FileSystemObject")
Set oInputFile = oFileSystem.OpenTextFile(INPUT_TEXT_FILE, 1, False)
Set oOutputFile = oFileSystem.OpenTextFile(Replace(INPUT_TEXT_FILE, sFileExt, "_" & iOutputFile & sFileExt), 2, True)
If REPEAT_HEADER_ROW Then
iLineCounter = 1
sHeaderLine = oInputFile.ReadLine()
Call oOutputFile.WriteLine(sHeaderLine)
End If
Do While Not oInputFile.AtEndOfStream
sLine = oInputFile.ReadLine()
Call oOutputFile.WriteLine(sLine)
iLineCounter = iLineCounter + 1
If iLineCounter Mod LINES_PER_PART = 0 Then
iOutputFile = iOutputFile + 1
Call oOutputFile.Close()
Set oOutputFile = oFileSystem.OpenTextFile(Replace(INPUT_TEXT_FILE, sFileExt, "_" & iOutputFile & sFileExt), 2, True)
If REPEAT_HEADER_ROW Then
Call oOutputFile.WriteLine(sHeaderLine)
End If
End If
Loop
Call oInputFile.Close()
Call oOutputFile.Close()
Set oFileSystem = Nothing
Call MsgBox("Done" & vbCrLf & "Lines Processed:" & iLineCounter & vbCrLf & "Part Files: " & iOutputFile & vbCrLf & "Start Time: " & sStart & vbCrLf & "Finish Time: " & Now())
Run Code Online (Sandbox Code Playgroud)
这个"File Splitter"Windows命令行程序运行良好:https://github.com/dubasdey/File-Splitter
它是开源的,简单的,记录的,经过验证的,并为我工作.
例:
fsplit -split 50 mb mylargefile.txt
Run Code Online (Sandbox Code Playgroud)