我有多个文本文件,大约有100,000行,我想将它们拆分成每行5000行的较小文本文件。
我用过:
split -l 5000 filename.txt
创建文件:
xaa
xab
aac
xad
xbe
aaf
没有扩展名的文件。我只想打电话给他们:
file01.txt
file02.txt
file03.txt
file04.txt
或者如果不可能,我只希望他们有“.txt”扩展名。
答案 0 :(得分:64)
我知道很久以前就已经问过这个问题,但我很惊讶没有人给出最简单的unix答案:
split -l 5000 -d --additional-suffix=.txt $FileName file
-l 5000
:将文件拆分为每行5,000行的文件。-d
:数字后缀。这将使后缀默认为00到99而不是aa到zz。--additional-suffix
:允许您指定后缀,此处为扩展名$FileName
:要拆分的文件的名称。file
:添加到结果文件的前缀。与往常一样,请查看man split
了解详情。
对于Mac,split
的默认版本显然是愚蠢的。您可以使用以下命令安装GNU版本。 (see this question for more GNU utils)
brew install coreutils
然后您可以将split
替换为gsplit
来运行上述命令。查看man gsplit
了解详情。
答案 1 :(得分:19)
以下是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);
答案 2 :(得分: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
这是一个应该完成任务的本机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
请注意,我使用了50000的llimit
进行测试。如果llimit
* 100比文件中的行数更接近,则会覆盖早期文件编号(通过将fcount
设置为1999
并使用~3
代替{来解决问题{1}}在文件重命名行中。)
答案 3 :(得分:8)
您可以使用awk
awk '{outfile=sprintf("file%02d.txt",NR/5000+1);print > outfile}' yourfile
基本上,它通过记录编号(NR)并将其除以5000来计算输出文件的名称,加1,将其整数和零填充加到2位。
默认情况下,awk
在您未指定任何其他内容时打印整个输入记录。因此,print > outfile
将整个输入记录写入输出文件。
当您在Windows上运行时,您不能使用单引号,因为它不喜欢它。我认为你必须把脚本放在一个文件中然后告诉awk
使用这个文件,如下所示:
awk -f script.awk yourfile
和script.awk
将包含如下脚本:
{outfile=sprintf("file%02d.txt",NR/5000+1);print > outfile}
或者,如果你这样做可能会有效:
awk "{outfile=sprintf(\"file%02d.txt\",NR/5000+1);print > outfile}" yourfile
答案 4 :(得分:7)
语法如下:
$ split [OPTION] [INPUT [PREFIX]]
其中前缀是 PREFIXaa,PREFIXab,...
只需使用正确的一个即可完成或只使用mv进行重命名。
我认为
$ mv * *.txt
应该工作,但首先在较小的规模上进行测试。
:)
答案 5 :(得分:5)
我的要求有点不同。我经常使用逗号分隔和制表符分隔的ASCII文件,其中单行是单个数据记录。而且它们非常大,所以我需要将它们分成可管理的部分(同时保留标题行)。
所以,我恢复了我的经典VBScript方法,并将一个小的.vbs脚本混合在一起,可以在任何Windows计算机上运行(它由Window上的WScript.exe脚本主机引擎自动执行)。
此方法的好处是它使用文本流,因此基础数据不会加载到内存中(或者至少不会一次加载到内存中)。结果是它非常快,并且它确实不需要太多内存来运行。我在i7上使用这个脚本分割的测试文件大约是1 GB的文件大小,有大约1200万行测试和25个部分文件(每个文件大约有500k行) - 处理大约需要2分钟而且没有任何时候都要使用超过3 MB的内存。
这里需要注意的是,它依赖于具有&#34; line&#34;的文本文件。 (意思是每个记录用CRLF分隔),因为文本流对象使用&#34; ReadLine&#34;用于一次处理一行的功能。但是,嘿,如果你正在使用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())
答案 6 :(得分:5)
这个“File Splitter”Windows命令行程序运行良好:https://github.com/dubasdey/File-Splitter
它是开源的,简单的,记录的,经过验证的,并为我工作。
示例:
fsplit -split 50 mb mylargefile.txt
答案 7 :(得分:2)
这是c#中的一个,当分成大块时不会耗尽内存!我需要将95M文件拆分为10M x行文件。
var fileSuffix = 0;
int lines = 0;
Stream fstream = File.OpenWrite($"{filename}.{(++fileSuffix)}");
StreamWriter sw = new StreamWriter(fstream);
using (var file = File.OpenRead(filename))
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
sw.WriteLine(reader.ReadLine());
lines++;
if (lines >= 10000000)
{
sw.Close();
fstream.Close();
lines = 0;
fstream = File.OpenWrite($"{filename}.{(++fileSuffix)}");
sw = new StreamWriter(fstream);
}
}
}
sw.Close();
fstream.Close();
答案 8 :(得分:0)
我为此创建了一个简单的程序,您的问题帮助我完成了解决方案...... 我添加了一个功能和一些配置。 如果你想在每几行之后添加一个特定的字符/字符串(可配置)。请仔细阅读说明。 我添加了代码文件: https://github.com/mohitsharma779/FileSplit