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

时间:2015-08-03 17:13:55

标签: batch-file dos

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

run_my_command | findstr "my_pattern"

但是看看findstr手册,似乎没有一个开关来打印所有东西(或模式之后的N行)。我不是DOS批次的专家,所以如果你有想法,请直接。

编辑:

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

  

...

     

...

     

21:23:26.332 [Thread-4] DEBUG o.s.b.f.s.DisposableBeanAdapter -   在bean上调用destroy(),名称为'ehcache'

     

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

     

21:23:26.332 [Thread-4] DEBUG net.sf.ehcache.CacheManager -   CacheManager已经关闭

     

结果:测试错误:ReceiptsSearchRequestBuilderTest.testCreateSearchRequest_loadDate:97»   IllegalArgument ReceiptLineControllerTest.testFind:26»NullPointer   测试运行:229,失败:0,错误:2,跳过:0

     

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

     

[INFO]建立失败

     

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

     

[INFO]总时间:23.213秒

     

[INFO]完成时间:2015-08-03T14:23:26-07:00

     

[INFO]最终记忆: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))}"

4 个答案:

答案 0 :(得分:0)

你是什么意思模式出现?你想找到哪里?由于你想要打印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
)

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

答案 1 :(得分:0)

当然,您需要执行通过管道连接的两个部件,就像您的示例一样。虽然可以在纯批处理中编写右侧管道进程,但批处理文件处理在从管道读取时会出现同步问题,因此我们需要使用不同的语言。

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的文件中;你需要在代码中调整一些细节。

答案 2 :(得分:0)

这里有一个使用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,以便在需要时保持控制台窗口打开。

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

@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' }"

答案 3 :(得分:0)

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

要跳过输出并使用以Results :

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

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

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

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

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

从以Results :

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

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

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