batch-file - 从文件中提取文本的批处理文件
问题描述
我有一个试图从中提取特定行的日志文件。当我将文件裁剪为上下几行时,我能够得到它。但是,我试图找到多个阻止使用 FULL 文件的实例。
以下是我尝试过的一些代码...
for /f "tokens=1* delims=[]" %%a in ('find /n " <Line Text="***********TEST1 TEST TEST************" />" ^< TEST.LOG') do (set H=%%a
)
for /f "tokens=1* delims=[]" %%a in ('find /n "</Report>" ^< TEST.LOG') do (
set T=%%a
)
for /f "tokens=1* delims=[]" %%a in ('find /n /v "" ^< TEST.LOG') do (
if %%a GEQ !H! if %%a LEQ !T! echo.%%b
)>> newfile.txt
我希望得到以下信息:
<Line Text="***********TEST1 TEST TEST************" />
~ALL LINES IN BETWEEN~
</Report>
解决方案
为执行命令和可执行文件而不是为文本文件处理而设计的 Windows 命令处理器绝对是过滤的最差选择TEST.LOG
。由于原因,请完整阅读我关于如何逐行读取和打印文本文件内容的答案?此处详细描述的批处理文件代码用作以下批处理文件代码的模板:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
if not exist "Test.log" goto EndBatch
set "OutputLines="
(for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "Test.log"') do (
set "Line=%%I"
setlocal EnableDelayedExpansion
if defined OutputLines (
echo(!Line:*:=!
if not "!Line:</Report>=!" == "!Line!" (
endlocal & set "OutputLines="
) else endlocal
) else if not "!Line:<Line Text=!" == "!Line!" (
echo(!Line:*:=!
endlocal & set "OutputLines=1"
) else endlocal
))>"newfile.txt"
if exist "newfile.txt" for %%I in ("newfile.txt") do if %%~zI == 0 del "newfile.txt"
:EndBatch
endlocal
此批处理文件将包含不区分大小写的字符串的行中的所有行写入包含不<Line Text
区分大小写的字符串</Report>
或文件结尾的行Test.log
到 file newfile.txt
。
注意:!Line:
and之间的搜索字符串=
不能包含等号,因为等号被 Windows 命令处理器解释为搜索字符串之间的分隔符,这里是</Report>
和<Line Text
,替换字符串,这里是两个空字符串。Windows 命令处理器将搜索字符串开头的星号*
解释为替换从行首到第一次出现的字符串替换的所有内容,而不是在行中查找的字符。但这对于这个用例来说并不重要。
如果标记要提取的块的开始和结束的两行是固定的并且不包含任何可变部分,则可以在没有字符串替换的情况下完成两个字符串比较,从而可以比较包含等号的字符串。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
if not exist "Test.log" goto EndBatch
set "BlockBegin= <Line Text="***********TEST1 TEST TEST************" />"
set "BlockEnd= </Report>"
set "OutputLines="
(for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "Test.log"') do (
set "Line=%%I"
setlocal EnableDelayedExpansion
if defined OutputLines (
echo(!Line:*:=!
if "!Line:*:=!" == "!BlockEnd!" (
endlocal & set "OutputLines="
) else endlocal
) else if "!Line:*:=!" == "!BlockBegin!" (
echo(!Line:*:=!
endlocal & set "OutputLines=1"
) else endlocal
))>"newfile.txt"
if exist "newfile.txt" for %%I in ("newfile.txt") do if %%~zI == 0 del "newfile.txt"
:EndBatch
endlocal
此变体将每一整行区分大小写与分配给环境变量的字符串进行比较,BlockBegin
并BlockEnd
确定从哪一行开始以及在哪一行停止输出行。
要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。
del /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
set /?
setlocal /?
也可以看看:
- 使用 Windows 批处理文件的具有多个命令的单行
- 这个答案是关于循环中需要的命令SETLOCAL和ENDLOCAL的详细信息,并且由于大量内存副本另外在后台完成,因此导致行的处理效率非常低下。
推荐阅读
- c# - 如何将异常从业务层引导到 UI 层
- mysql - 当我尝试从 docker-compose docker-compose 我的 .sql 文件时出错
- c++ - 宁静书商项目
- c - 为什么我在终端中看不到完整的 Linux 内核崩溃,但可以通过 COM 端口看到?
- c# - JanusGraph .net C#
- python - 在 Jupyter Notebook 中读取一个巨大的 .csv 文件
- git - 是否会推送大型还原的 git 提交?
- javascript - 在three.js中如何使球体锐利?
- python - Newbee 终端将 Flask 添加到路径
- amazon-web-services - 公共子网中的 Lambda 函数无法访问私有子网中的资源