Batch file 真正合并到.bat文件中
如何将两个文本文件合并到一个.bat文件中? 或者至少如何读取.bat文件中文件的下一行/测试结尾 是否可以使用.bat脚本合并两个文本文件? 其思想不是附加或连接,而是基于每行的内容执行合并操作。 一个简化的示例是从两个排序文件生成一个排序文件,如伪代码(伪代码,因为我似乎找不到读取下一行并测试读取文件结尾的方法–在for循环之外)Batch file 真正合并到.bat文件中,batch-file,Batch File,如何将两个文本文件合并到一个.bat文件中? 或者至少如何读取.bat文件中文件的下一行/测试结尾 是否可以使用.bat脚本合并两个文本文件? 其思想不是附加或连接,而是基于每行的内容执行合并操作。 一个简化的示例是从两个排序文件生成一个排序文件,如伪代码(伪代码,因为我似乎找不到读取下一行并测试读取文件结尾的方法–在for循环之外) :顶部 设置/p行1读取行(文件1) :设置/p行2读取行(文件2) :测试 如果EOF(文件1)转到FINISH2 如果EOF(文件2)转到FINISH1 如果
:顶部
设置/p行1读取行(文件1)
:设置/p行2读取行(文件2)
:测试
如果EOF(文件1)转到FINISH2
如果EOF(文件2)转到FINISH1
如果%Line1%<%Line2%
(回显%Line1%-不在2>>文件3中
设置/p行1=读取行(文件1)
转到测试)
如果%Line1%>%Line2%
(回显%Line2%-不在1>>文件3中
设置/p行2=读取行(文件2)
转到测试)
ELSE在两个>>文件中都回显%Line1%3
转到顶端
:FINISH1
回显%Line2%-不在1>>文件3中
设置/p行1=读取行(文件1)
如果不是(EOF(文件1))
(回显%Line1%-不在2>>文件3中
转到完成1)
否则转到EOF
:FINISH2
回显%Line2%-不在1>>文件3中
设置/p行2=读取行(文件2)
如果不是(EOF(文件1))
(回显%Line2%-不在1>>文件3中
GOTO FINISH2)
我尝试了for循环,但是循环内部的分支似乎阻止了循环。我尝试了各种方法(包括parallel.bat)来找到一种方法,使用set
和2个步骤在文件中移动光标(不需要排序,因为步骤2中的find
会检查新文件,只有在找不到数据时才会写入内容):
合并文件:
copy file1.txt+file2.txt file3.txt
删除重复行(/i
忽略大小写,如果将Fred
和Fred
视为不同,则省略):
结果文件为file4.txt
2个步骤(不需要排序,因为步骤2中的find
检查新文件,并且仅在未找到数据时写入内容):
合并文件:
copy file1.txt+file2.txt file3.txt
删除重复行(/i
忽略大小写,如果将Fred
和Fred
视为不同,则省略):
结果文件是file4.txt
批处理对于文本处理来说确实是一种糟糕的“语言”。几乎你能找到的任何其他工具都比批处理更好(更容易开发,执行更快)。我提供批处理解决方案是因为我喜欢这个挑战,但我总是会推荐一些其他语言或工具来代替批处理来进行文本处理。话虽如此
假设两个源文件都已排序
@echo off
setlocal enableDelayedExpansion
::define the files
set "in1=file1.txt"
set "in2=file2.txt"
set "out=file3.txt"
::define some simple macros
set "eof1=^!ln1^! gtr ^!cnt1^!"
set "eof2=^!ln2^! gtr ^!cnt2^!"
set "read1=if ^!ln1^! leq ^!cnt1^! set "txt1=" & <&3 set /p "txt1=" & set /a ln1+=1"
set "read2=if ^!ln2^! leq ^!cnt2^! set "txt2=" & <&4 set /p "txt2=" & set /a ln2+=1"
set "write1=echo(^!txt1^! - not in 2"
set "write2=echo(^!txt2^! - not in 1"
set "writeBoth=echo(^!txt1^! - in both"
::count the number of lines in each file
for /f %%N in ('find /v /c "" ^<"%in1%"') do set "cnt1=%%N"
for /f %%N in ('find /v /c "" ^<"%in2%"') do set "cnt2=%%N"
::setup redirection in outer block and merge the files in a loop
::The max number of iterations assumes there is no overlap (cnt1+cnt2)
::Break out of the loop as soon as both files have reached EOF.
set /a ln1=0, ln2=0, cnt=cnt1+cnt2
4<"%in2%" 3<"%in1%" (
%read1%
%read2%
for /l %%N in (1 1 %cnt%) do (
if %eof1% (
if %eof2% goto :break
%write2%
%read2%
) else if %eof2% (
%write1%
%read1%
) else if .!txt1! lss .!txt2! (
%write1%
%read1%
) else if .!txt2! lss .!txt1! (
%write2%
%read2%
) else (
%writeBoth%
%read1%
%read2%
)
)
) >"%out%
:break
对于文本处理来说,批处理确实是一种糟糕的“语言”。几乎你能找到的任何其他工具都比批处理更好(更容易开发,执行更快)。我提供批处理解决方案是因为我喜欢这个挑战,但我总是会推荐一些其他语言或工具来代替批处理来进行文本处理。话虽如此
假设两个源文件都已排序
@echo off
setlocal enableDelayedExpansion
::define the files
set "in1=file1.txt"
set "in2=file2.txt"
set "out=file3.txt"
::define some simple macros
set "eof1=^!ln1^! gtr ^!cnt1^!"
set "eof2=^!ln2^! gtr ^!cnt2^!"
set "read1=if ^!ln1^! leq ^!cnt1^! set "txt1=" & <&3 set /p "txt1=" & set /a ln1+=1"
set "read2=if ^!ln2^! leq ^!cnt2^! set "txt2=" & <&4 set /p "txt2=" & set /a ln2+=1"
set "write1=echo(^!txt1^! - not in 2"
set "write2=echo(^!txt2^! - not in 1"
set "writeBoth=echo(^!txt1^! - in both"
::count the number of lines in each file
for /f %%N in ('find /v /c "" ^<"%in1%"') do set "cnt1=%%N"
for /f %%N in ('find /v /c "" ^<"%in2%"') do set "cnt2=%%N"
::setup redirection in outer block and merge the files in a loop
::The max number of iterations assumes there is no overlap (cnt1+cnt2)
::Break out of the loop as soon as both files have reached EOF.
set /a ln1=0, ln2=0, cnt=cnt1+cnt2
4<"%in2%" 3<"%in1%" (
%read1%
%read2%
for /l %%N in (1 1 %cnt%) do (
if %eof1% (
if %eof2% goto :break
%write2%
%read2%
) else if %eof2% (
%write1%
%read1%
) else if .!txt1! lss .!txt2! (
%write1%
%read1%
) else if .!txt2! lss .!txt1! (
%write2%
%read2%
) else (
%writeBoth%
%read1%
%read2%
)
)
) >"%out%
:break
为什么不简单地使用diff/merge实用程序呢?欢迎用户1495762。请使用编辑框上方的按钮提供的这一面的标记,但不要使用一些不起作用的自创语法。有关更多信息,请阅读常见问题解答。谢谢。这里有一些GNU工具:join
,sort-m
,combine
等等。你可以获得我安装的cygwin的大部分信息。cygwin还提供了一个更好的shell/命令行解释器,名为bash。sort
也在dos中使用了很长一段时间——在XP中,它将是copy file1.txt+file2.txt file3.txt
然后sortedfile3.txt/o sortedfile3.txt
,原始文件不需要sorted@SeanCheshire-但这不会合并文件。如果一行同时出现在两个源中,则在输出中只应出现一次。您的建议将在输出中放置该行的两个副本。为什么不简单地使用diff/merge实用程序呢?欢迎使用1495762。请使用编辑框上方的按钮提供的这一面的标记,但不要使用一些不起作用的自创语法。有关更多信息,请阅读常见问题解答。谢谢。这里有一些GNU工具:join
,sort-m
,combine
等等。你可以获得我安装的cygwin的大部分信息。cygwin还提供了一个更好的shell/命令行解释器,名为bash。sort
也在dos中使用了很长一段时间——在XP中,它将是copy file1.txt+file2.txt file3.txt
然后sortedfile3.txt/o sortedfile3.txt
,原始文件不需要sorted@SeanCheshire-但这不会合并文件。如果一行同时出现在两个源中,则在输出中只应出现一次。您的建议将在输出中放置该行的2个副本。+1,简单合并的优雅解决方案,假设所有DUP都应删除。虽然不确定性能,但为每行调用FIND可能会大大降低速度。这不能像OP最初在伪代码中显示的那样跟踪哪些行来自何处。使用“复制”选项可防止添加
。循环体可以简化为find/i“%%a”file4.txt>nul | echo%%a>>file4.txt
woops,最终输出需要排序以满足操作要求sort file4.txt/o file5.txt
,但您的解决方案更优雅+1,简单合并的优雅解决方案,假设所有DUP都应该删除。虽然不确定性能,但为每行调用FIND可能会大大降低速度。这不能像OP最初在伪代码中显示的那样跟踪哪些行来自何处。使用“复制”选项可防止添加
。循环体可以简化为find/i“%%a”file4.txt>nul | | echo%%a>>file4.txt
woops,final
@echo off
setlocal enableDelayedExpansion
::define the files
set "in1=file1.txt"
set "in2=file2.txt"
set "out=file3.txt"
::define some simple macros
set "eof1=^!ln1^! gtr ^!cnt1^!"
set "eof2=^!ln2^! gtr ^!cnt2^!"
set "read1=if ^!ln1^! leq ^!cnt1^! set "txt1=" & <&3 set /p "txt1=" & set /a ln1+=1"
set "read2=if ^!ln2^! leq ^!cnt2^! set "txt2=" & <&4 set /p "txt2=" & set /a ln2+=1"
set "write1=echo(^!txt1^! - not in 2"
set "write2=echo(^!txt2^! - not in 1"
set "writeBoth=echo(^!txt1^! - in both"
::count the number of lines in each file
for /f %%N in ('find /v /c "" ^<"%in1%"') do set "cnt1=%%N"
for /f %%N in ('find /v /c "" ^<"%in2%"') do set "cnt2=%%N"
::setup redirection in outer block and merge the files in a loop
::The max number of iterations assumes there is no overlap (cnt1+cnt2)
::Break out of the loop as soon as both files have reached EOF.
set /a ln1=0, ln2=0, cnt=cnt1+cnt2
4<"%in2%" 3<"%in1%" (
%read1%
%read2%
for /l %%N in (1 1 %cnt%) do (
if %eof1% (
if %eof2% goto :break
%write2%
%read2%
) else if %eof2% (
%write1%
%read1%
) else if .!txt1! lss .!txt2! (
%write1%
%read1%
) else if .!txt2! lss .!txt1! (
%write2%
%read2%
) else (
%writeBoth%
%read1%
%read2%
)
)
) >"%out%
:break
@echo off
setlocal disableDelayedExpansion
set lf=^
::above 2 blank lines required
copy /b file1.txt+file2.txt file3.txt >nul
set "old="
(
for /f eol^=^%lf%%lf%^ delims^= %%A in ('sort file3.txt') do (
set "new=.%%A"
setlocal enableDelayedExpansion
if "!old!" neq "!new!" echo(!new:~1!
for /f "delims=" %%B in ("!new!") do (
endlocal
set "old=%%B"
)
)
)>file4.txt