在 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 -arguments
和 string_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"
使用 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 -arguments
和string_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"