如何在特定单词到段落末尾之后从日志文件中打印所有行?

问题描述 投票:0回答:1

我有一个如下日志文件:

Beginning difffull backup for database Managed_Metadata_Service, 3 of 149.
Full: 0   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Full: 4   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Backup of Managed_Metadata_Service failed.
ANS0238E (RC2041) The sequence of calls is invalid.

Beginning difffull backup for database model, 4 of 149.
Full: 0   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Full: 2   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Full: 4   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Backup of model failed.
ANS0238E (RC2041) The sequence of calls is invalid.

Beginning difffull backup for database msdb, 5 of 149.
Full: 0   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Full: 4   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Backup of msdb failed.
ANS0238E (RC2041) The sequence of calls is invalid.

Beginning difffull backup for database Search_Service_Application_AnalyticsReportingStoreDB, 6 of 149.
Full: 0   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Full: 4   Read: 6144  Written: 0  Rate: 0.00 Kb/Sec
Backup of Search_Service_Application_AnalyticsReportingStoreDB failed.
ANS0238E (RC2041) The sequence of calls is invalid.

如何找到所有出现的failed,然后用这个单词和下一行打印行直到消息结束,这意味着直到段末或文件末尾的下一个点?

结果将是这样的:

Backup of Managed_Metadata_Service failed. 
ANS0238E (RC2041) The sequence of calls is invalid.
.
.
Search_Service_Application_AnalyticsReportingStoreDB failed. 
ANS0238E (RC2041) The sequence of calls is invalid.

对于failed字的所有行。

这是我到目前为止的代码:

@echo off
setlocal EnableDelayedExpansion
set numbers=
for /F "delims=^" %%a in ('findstr /I /N /C:"failed" Backup_DIFF_2017-12-14.log') do (
    set /A sameline=%%a, after=%%a+1
    set "numbers=!numbers!!sameline!: !after!: "
)
rem Search for the lines
(
    for /F "tokens=* delims=^ %%a in ('findstr /N "^" Backup_DIFF_2017-12-14.log ^| findstr /B "%numbers%"') do echo %%b
) > result.txt
windows batch-file text
1个回答
1
投票

Stephan为此日志文件示例建议的简单解决方案是:

@%SystemRoot%\System32\findstr.exe "failed\.$ ^ANS" "Backup_DIFF_2017-12-14.log"

这条命令行输出:

Backup of Managed_Metadata_Service failed.
ANS0238E (RC2041) The sequence of calls is invalid.
Backup of model failed.
ANS0238E (RC2041) The sequence of calls is invalid.
Backup of msdb failed.
ANS0238E (RC2041) The sequence of calls is invalid.
Backup of Search_Service_Application_AnalyticsReportingStoreDB failed.
ANS0238E (RC2041) The sequence of calls is invalid.

FINDSTR搜索以failed.结尾的行或以ANS开头的行并输出这些行。点必须位于正则表达式搜索字符串中,并使用反斜杠将其解释为文字字符。 FINDSTR不支持多行正则表达式搜索。

备用FINDSTR命令行还在每行或组合上运行两个正则表达式搜索:

@%SystemRoot%\System32\findstr.exe /R /C:failed\.$ /C:^ANS "Backup_DIFF_2017-12-14.log"

更复杂的解决方案是使用此批处理代码:

@echo off
if not exist "Backup_DIFF_2017-12-14.log" goto :EOF

setlocal EnableExtensions EnableDelayedExpansion
set "PrintLines="

for /F "tokens=1* delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /N /R "^" "Backup_DIFF_2017-12-14.log"') do (
    if "%%J" == "" (
        set "PrintLines="
    ) else (
        set "Line=%%J"
        if not "!Line:failed=!" == "!Line!" set "PrintLines=1"
    )
    if defined PrintLines echo %%J
)

endlocal

输出是一样的。此代码输出包含任何不区分大小写的failed的任何行,并将此行以及所有其他行输出到文件中的下一个空行。空行不包含任何字符,甚至不包含空格或水平制表符。

此代码有两个问题:

  1. 以一个或多个冒号开头的行不正确输出,因为行开头的所有冒号都被delims=:删除,需要将FINDSTR的每一行输出拆分为行号,冒号和行本身。 FINDSTR用于处理FOR甚至空行,因为包含空行的所有行在文件搜索行的FINDSTR之后以行号和冒号开头,行的开始导致每行的正匹配。
  2. 包含一个或多个感叹号的行不正确输出,因为在用文件中的行替换set "Line=%%J"后,在命令行%%J上应用了启用的延迟环境变量扩展。

另一种不是100%完美的解决方案

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "PrintLines="

for /F "usebackq delims=" %%I in ("Backup_DIFF_2017-12-14.log") do (
    set "Line=%%I"
    if "!Line:~0,9!" == "Beginning" (
        set "PrintLines="
    ) else (
        if not "!Line:failed=!" == "!Line!" set "PrintLines=1"
    )
    if defined PrintLines echo %%I
)

endlocal

与第二个解决方案相比,此批处理代码将行开头的区分大小写的Beginning解释为新段而不是空行。因此,命令FOR可以直接处理文件而忽略空行。

但是这个解决方案还有两个问题:

  1. FOR忽略以分号开头的行,因为;是未明确设置为其他字符的选项eol的默认值。这个问题可以通过指定eol=来解决,该字符在日志文件的一行的开头肯定不存在。
  2. 包含一个或多个感叹号的行不正确输出,因为在用文件中的行替换set "Line=%%I"后,在命令行%%I上应用了启用的延迟环境变量扩展。

这个解决方案期望从Beginning开始的行在行中的任何地方都不包含单词failed


要了解使用的命令及其工作方式,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。

  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?
© www.soinside.com 2019 - 2024. All rights reserved.