在 DOS 批处理文件中找到匹配项后如何打印所有控制台输出?

How to print all console output after a match is found in a DOS batch file?

使用 DOS 批处理语法,我需要等到模式出现在控制台输出中,然后打印之后的所有内容(或者至少在匹配后打印 N 行)。我怎样才能做到这一点? (类似于 Unix 中的 grep +A)。我可以简单地这样做,以获得模式:

run_my_command | findstr "my_pattern"

但是查看 findstr 手册,似乎没有一个开关可以打印所有内容(或模式后的 N 行)。我不是DOS批处理的专家,所以如果你有想法,请直接。

编辑:

这是我输出的最后一部分(即这些行之前有很多行,但我感兴趣的是测试结果,即 "Results :" 之后的所有内容都是粗体)

...

...

21:23:26.332 [Thread-4] DEBUG o.s.b.f.s.DisposableBeanAdapter - Invoking destroy() on bean with name 'ehcache'

21:23:26.332 [Thread-4] INFO o.s.c.e.EhCacheManagerFactoryBean - Shutting down EhCache CacheManager

21:23:26.332 [Thread-4] DEBUG net.sf.ehcache.CacheManager - CacheManager already shutdown

Results : Tests in error: ReceiptsSearchRequestBuilderTest.testCreateSearchRequest_loadDate:97 » IllegalArgument ReceiptLineControllerTest.testFind:26 » NullPointer Tests run: 229, Failures: 0, Errors: 2, Skipped: 0

[INFO] ----------------------------------

[INFO] BUILD FAILURE

[INFO] ----------------------------------

[INFO] Total time: 23.213 s

[INFO] Finished at: 2015-08-03T14:23:26-07:00

[INFO] Final Memory: 19M/453M

[INFO] -------------------------------

编辑:

这是我的脚本。当我不重定向到 %log% 时,它只会在我的模式之后打印文本,这正是我想要的。但是当我将它重定向到 %log% 时,日志文件包含所有文本(stderr 也正确地转储为 null)。

@echo OFF

SET MAVEN_PROFILE=ie
SET root_dir="%USERPROFILE%\Desktop\MyFolder"
SET log=%root_dir%/log.txt

powershell -c "$txt=(&mvn -P %MAVEN_PROFILE% -Dtest=LoginTest test > %log% 2> null) -join \"`r`n\"; $i=$txt.indexof('Results :'); if($i -ge 0) { $j=$txt.lastindexof(\"`n\",$i); write-host $txt.substring([math]::max(0,$j+1))}"

出现模式是什么意思?您想在哪里找到?由于您想打印 N 行或之后的所有内容,我假设您是在文本文件中搜索单词而不是模式。

@echo off
set /p word = What word/pattern you are searching for? ^>
set bool = 0

for /f "tokens=*" %%a in (Text.txt) do (
    if %%a == %word% set bool = 1
    if %bool% == 1 echo %%a
)

此脚本仅在找到您要查找的单词后打印所有内容。

当然,您需要执行通过管道连接的两个部分,就像在您的示例中一样。虽然可以用纯Batch来写右边的pipe过程,但是batch文件处理在从pipe读取时存在同步问题,所以我们需要使用不同的语言。

JScript 是一种比 Batch 更强大的编程语言,从 XP 开始的所有 Windows 版本都可用,而且很容易将 Batch 和 JScript 代码组合在同一个 混合脚本:

编辑:第一行缺少 @。固定

@set @Batch=1 /*
@echo off
run_my_command | CScript //nologo //E:JScript "%~F0"
goto :EOF    */

// JScript section

var lineFound = false, numOfLines = N;
while ( ! WScript.Stdin.AtEndOfStream ) {
   line = WScript.Stdin.ReadLine();
   if ( ! lineFound  &&  line.indexOf("my_pattern") >= 0 ) lineFound = true;
   if ( lineFound  &&  numOfLines ) {
      WScript.Stdout.WriteLine(line);
      --numOfLines;
   }
}

将之前的代码保存在扩展名为.bat的文件中;您需要调整代码中的一些细节。

这是一个使用 powershell 的单行代码,您可以从批处理文件中运行,在 120MB 输出的末尾找到一个字符串需要 10 秒:

powershell -c "$txt=(&your_console_app -with -arguments) -join \"`r`n\"; $i=$txt.indexof('string_to_search_for'); if($i -ge 0) { $j=$txt.lastindexof(\"`n\",$i); $txt.substring([math]::max(0,$j+1)) }"
  • 相应地替换 your_console_app -with -argumentsstring_to_search_for。如果那些包含双引号将它们转义为 \".
  • 在新行中添加 pause 以保持控制台 window 在需要时打开。

使用实际命令行输出到重定向到文件的标准输出的示例:

@echo OFF

SET MAVEN_PROFILE=ie
SET root_dir="%USERPROFILE%\Desktop\MyFolder"
SET log=%root_dir%/log.txt

powershell -c "$txt=(&mvn -P %MAVEN_PROFILE% -Dtest=LoginTest test 2>nul) -join \"`r`n\"; $i=$txt.indexof('Results :'); if($i -ge 0) { $j=$txt.lastindexof(\"`n\",$i); $txt.substring([math]::max(0,$j+1)) }" >results.txt

或者,您可以直接从 powershell 代码中写入文件:

powershell -c "$txt=(&mvn -P %MAVEN_PROFILE% -Dtest=LoginTest test 2>nul) -join \"`r`n\"; $i=$txt.indexof('Results :'); if($i -ge 0) { $j=$txt.lastindexof(\"`n\",$i); $txt.substring([math]::max(0,$j+1)) | out-file 'results.txt' }"

这是一个与 Aacini 的答案类似的想法,不同之处在于它使用了一个名为 JREPL.BAT 的已编写的混合 JScript/batch 实用程序,它提供复杂的正则表达式文本处理功能以进行批处理。 JREPL.BAT 是纯脚本,可​​以在任何 Windows XP 以后的机器上本地运行。脚本中嵌入了完整的文档。

跳过输出并从以 Results :

开头的第一行开始打印
yourCommand | jrepl "^Results :[\s\S]*" "[=10=]" /jmatch /m

仅打印以 Results : 开头的行,加上接下来的 4 行(共 5 行)

yourCommand | jrepl "^Results :(.*\n){0,4}.*$" "[=11=]" /jmatch /m

上面的两个命令都使用了/M 多行选项,这意味着必须将整个输出加载到内存中。命令完成之前不会打印任何内容。如果输出是几千兆字节,或者如果它很长 运行,并且您想尽快看到输出,这可能是个问题。

使用更多代码和用户提供的 JScript,可以独立处理和打印每一行 - 没有延迟,也没有大小限制:

打印以 Results :

开头的第一行开始的所有内容
yourCommand | jrepl "^Results :.*|^.*" "go=true;[=12=]|go?[=12=]:false" /jmatch /t "|" /jbeg "var go=false"

仅打印以 Results : 开头的行,加上接下来的 4 行(共 5 行)

yourCommand | jrepl "^Results :.*|^.*" "go=5;[=13=]|(--go>0)?[=13=]:false" /jmatch /t "|" /jbeg "var go=0"