【问题标题】:Batch script to grab lines with findstr without filepath用 findstr 抓取行的批处理脚本,没有文件路径
【发布时间】:2015-03-31 17:22:46
【问题描述】:

我有一个日志文件,用于监控包括请求和确认在内的大型系统。我的目标是能够:

1. 循环遍历脚本并获取请求及其确认发生的行

2. 将所有重要的行作为字符串提取,并将它们存储为变量,以便字符串修改以输出到其他地方。

这是我目前所拥有的:

@ECHO off
setlocal
setlocal enabledelayedexpansion
setlocal enableextensions

:: Lets get today's date, formatted the way the ABCD File is named
for /f "tokens=1-5 delims=/ " %%d in ("%date%") do set targetDate=%%f-%%d-%%e
:: Now we set the targetFile name
SET ABCDLogsFile=C:\Users\me\Documents\monitoring_file_for_jim\ABCDFIX*%targetDate%.log
::****Scrapped original approach*****
set "ackFoundCount=0"
set "reqFoundCount=0"
::Get lines with acks
for /f delims^=^ eol^= %%a in ('findstr /c:"\<ACK\>" "%ABCDLogsFile%"') do (
    set /a "ackFoundCount+=1"
    setlocal enabledelayedexpansion
    for %%N in (!ackFoundCount!) do (
        endlocal
        set "ackFound%%N=%%a"
    )
)
::Get lines with requests
for /f delims^=^ eol^= %%b in ('findstr /c:"ReqSingle" "%ABCDLogsFile%"') do (
    set /a "reqFoundCount+=1"
    setlocal enabledelayedexpansion
    for %%N in (!reqFoundCount!) do (
        endlocal
        set "reqFound%%N=%%b"
    )
)

setlocal enabledelayedexpansion
for /l %%N in (1,1,2 %reqFoundCount%) do echo REQ %%N FOUND= !reqFound%%N!
pause
for /l %%N in (1,1,2 %ackFoundCount%) do echo ACK %%N FOUND= !ackfound%%N!
endlocal

编辑 2 dbenham

我之前试图实现这一点的迂回方式完全没有必要。 感谢这里的问题和答案:

'findstr' with multiple search results (BATCH)

我的脚本工作类似。但是,我很好奇是否有可能在开头没有文件路径的情况下获得 findstr 输出。我只需要对日志中的时间戳进行子串化,它始终是每行的前 12 个字符(没有文件路径)。我的输出当前以路径为前缀,虽然我可以获得日志最终在生产中的路径,但尝试另一种方式会更安全。在最终运行此脚本时,每个只有 1 或 2 个请求和确认,这就是我存储所有找到的原因。没有必要,但我认为如果有两个,看到两个会让人放心。以下是acks 和reqs 类似的输出:

C:\Users\me\Documents\monitoring_file_for_jim\ABCDFIX 2015-04-01.log:2015-03-26 07:00:11,028 INFO  etc...

我在想,如果我可以从一开始就去掉文件路径,那么我需要做的就是只是事件的时间戳

for /l %%N in (1,1,1 %reqFoundCount%) do echo Req %%N occurred at: !reqFound%%N:~0,12! >> MorningAckChecks.txt
for /l %%N in (1,1,1 %ackFoundCount%) do echo ACK %%N occurred at: !ackfound%%N:~0,12! >> MorningAckChecks.txt

【问题讨论】:

  • > “我试图使用带有这些变量的 for /f 作为参数来跳过和抓取这些行,但我似乎无法正确地做到这一点” - 请也发布此代码。
  • 不轻易使用powershell!只需Select-String -Pattern "stack" -List -SimpleMatch -Path F:\Andorid\Andorid.vmx | select Line,LineNumber,您就可以非常简单地获得与您的模式和行号匹配的行!
  • 我正在考虑使用 powershell 来执行此操作,但在建议我这样做的潜在解决方案中,没有建议我使用“powershell”。

标签: batch-file for-loop batch-processing findstr logfile


【解决方案1】:

我怀疑您无法让 SKIP 工作,因为您正在使用 FOR 语句迭代分隔的行号列表,这意味着该数字位于 FOR 变量中。问题是,在指定 SKIP 值或任何其他 FOR 选项时,您不能包含 FOR 变量或(延迟扩展)。批处理解析器在扩展 FOR 变量之前评估 FOR 选项,因此它不可能工作。当包含变量作为 FOR 选项的一部分时,只能使用普通扩展。

但我不明白你为什么认为你需要行号。 FINDSTR 已经能够解析出您想要的行。只需使用 FOR /F 迭代每个匹配的行。对于每一行,定义一个包含行内容的变量,然后使用子字符串操作解析出你想要的值。

但我可以提供一个我认为可以让您的生活更轻松的替代方案。 JREPL.BAT 是一个复杂的正则表达式文本处理器,可以一次性识别行并解析和转换您想要的值。 JREPL.BAT 是一个混合 JScript/批处理脚本,可以在 XP 以后的任何 Windows 机器上本地运行。

如果我知道您的输入是什么样的,以及您想要的输出是什么,那么我可能会使用JREPL.BAT 提出一个简单的解决方案。或者您可以阅读大量的内置文档并自己弄清楚。

通过jrepl /? 从命令行访问文档。您可能希望通过 MORE 管道输出,以便一次获得一屏帮助。但我从不这样做,因为我的命令行控制台配置了一个大的输出缓冲区,所以我可以简单地向上滚动查看过去的输出。


编辑 - 回应评论和更新的问题

这是导致问题的代码的相关 sn-ps。

SET ABCDLogsFile=C:\Users\me\Documents\monitoring_file_for_jim\ABCDFIX*%targetDate%.log
findstr /c:"\<ACK\>" "%ABCDLogsFile%"
findstr /c:"ReqSingle" "%ABCDLogsFile%

问题是您的 ABCDLogsFile 定义包含一个通配符,这会导致 FINDSTR 在每个匹配行前面加上匹配发生的文件名的完整路径。

我有一个简单的解决方案 - 只需将 ABCDLogsFile 的定义更改如下:

SET "ABCDLogsFile=C:\Users\me\Documents\monitoring_file_for_jim\ABCDFIX<%targetDate%.log"

解释

我的解决方案依赖于两个未记录的功能

1) 未记录的文件掩码通配符。

  • &lt; - 非常类似于 *
  • &gt; - 非常类似于 ?

这些符号通常用于重定向,因此如果您想将它们用作文件掩码通配符,它​​们必须被引用或转义。

我们在 DosTips - Dir undocumented wildcards 讨论未记录的功能。贯穿整个线程(和链接)的是一些示例用例。

我在http://www.dostips.com/forum/viewtopic.php?p=39420#p39420记录了我对非标准通配符工作原理的理解

2) FINDSTR 使用非标准通配符

如果出现以下任何情况,FINDSTR 将在每个匹配行前加上文件名(可能还有路径)

  • 使用了/M 选项
  • 使用了/F 选项
  • 在命令行中明确列出了多个输入文件
  • 通过文件掩码隐含多个输入文件,在命令行中至少包含一个*? 通配符

由于最后一个触发器 - 您的文件掩码中的 *,您正在获取文件路径前缀。

但您可以改用&lt; 来获得相同的结果,除了非标准通配符不会触发输出中的文件前缀。

问题解决了:-)

我在 http://www.dostips.com/forum/viewtopic.php?p=39464#p39464 谈论这个 FINDSTR 功能。

有一天我希望用这个美味的小消息更新我的What are the undocumented features and limitations of the Windows FINDSTR command? 帖子。

【讨论】:

  • 我看到很多人在各种批处理问题中谈论 JREPL.bat!如果它可以帮助解决我的问题,我现在肯定会研究它。如果 FINDSTR 已经可以为我完成这项工作,我很清楚我是一个整体的新手,我只是不确定 FINDSTR 是否可以找到我想要的字符串,然后只需将它包含在其中的整行并将其存储在一个变量中。我肯定得在早上再看一看。感谢 dbenham 的回复,您的批处理向导状态在您之前。
  • 你能看看我所做的编辑吗?我很好奇是否有办法从 FINDSTR 的输出中删除文件路径。
  • @driftandwander - 是原始文件中的路径,还是由 FINDSTR 添加的?如果它在原始文件中,则 FINDSTR 无法将其删除。但是 JREPL 可以很容易地做到这一点。如果路径是由 FINDSTR 添加的,那么可能有一种方法可以避免它,这取决于触发路径添加的原因。你应该展示你的代码。
  • 对不起,我已经添加了代码。路径来自 FINDSTR,到目前为止,我已经看到 FINDSTR 总是在其输出前加上其结果的文件路径。我可以在知道该脚本在生产中运行时日志文件实际在哪里的情况下对当前结果进行子串化,但我认为如果可能的话,最好以另一种方式删除文件路径。
  • @driftandwander - 查看我的更新答案 - 我有一个简单的解决方案!
【解决方案2】:

这篇文章变得有点混乱。如果您发布与您获得的输出相对应的输入行,那将非常有帮助。如果你不能这样做,那么在你的 FOR 之前添加这个语句。我相信你会发现 testReqSkip 是空白的。

echo.testReqSkip=%testReqSkip%

【讨论】:

  • 哦,testReqSkip 的值是@@, 264, 296@@,在原帖中。很抱歉这篇文章不再清楚,我目前不在我的工作站,当我再次访问它时能够澄清更多。真的很抱歉!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多