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

时间:2017-12-21 15:09:44

标签: windows batch-file text

我有一个如下所示的日志文件:

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

1 个答案:

答案 0 :(得分: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 命令行还在每行 OR 上运行两个正则表达式搜索:

@%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上应用了启用的延迟环境变量扩展。
  3. 另一个不是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上应用了启用的延迟环境变量扩展。
    3. 此解决方案预计以Beginning开头的行在该行的任何位置都不包含单词failed

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

      • echo /?
      • endlocal /?
      • findstr /?
      • for /?
      • goto /?
      • if /?
      • set /?
      • setlocal /?