我正在尝试使用Windows批处理文件将数据从stdin(到日志文件)中加时间戳

Dee*_*old 6 windows pipe batch-file

我正在使用wget的DOS端口从API收集数据,以生成日志文件的数据(将在以后进行分析).除了当前时间之外,API提供了我需要的所有信息(它在数据流开始时提供时间,但在此之后不再提供时间).

API通常最初提供10行数据,然后每20-30秒提供一行.

我正在尝试为此输出添加时间戳并将其复制到日志文件中 - 我不介意时间戳与输出的其余部分或之前的行位于同一行.

我首先开始使用这个批处理文件:

addtimes.bat:

@echo off >nul
:start
set /p input="":

echo %time% 
echo %input%

goto:start
Run Code Online (Sandbox Code Playgroud)

(称为"wget ..... | addtimes.bat> log.log")

然而,这些数据丢失了 - 许多数据线的开头都丢失了.

我在这里看了一下,意识到我应该使用for循环.

addtimes2.bat:

@echo off
cls
setlocal EnableDelayedExpansion
for /F "tokens=*" %%a in ('more') do ( 
echo !time! %%a )
)
Run Code Online (Sandbox Code Playgroud)

我尝试过使用和不启用延迟扩展.

我似乎无法使用不同的时间戳一次传递一行信息 - 一旦我关闭数据流,我的所有行都会得到相同的时间戳.

典型的输入数据形式如下:

[1,"219","265",14528,1359031137000,1359031137000]
[1,"6594","358",18188,1359031019000,1359031019000]
[1,"690","94",15920,1359031534000,1359031534000]
[1,"25164","102",2129,1359031457000,1359031457000]


[1,"3488","329",2109,1359030868000,1359030868000]

[1,"37247","6",11506,1359031223000,1359031223000]
Run Code Online (Sandbox Code Playgroud)

您可能会注意到数据中存在UTC时间,但它们不是当前时间.

dbe*_*ham 4

我不相信您可以使用纯本机批处理获得您想要的结果。所有时间都相同的原因是 FOR /F 循环不会处理任何输入行,直到整个输入流被缓冲(管道左侧的命令已完成)。FOR /F 命令等待,直到收到所有输入,然后疯狂地转储每一行。如果输入流足够大,您将在时间上得到轻微的变化,但没有任何接近表示原始命令生成每一行的时间。

这是一个混合 JScript/批处理脚本,可以完成您想要的操作。它作为一个直接的 JScript 文件可以正常工作,但是您需要明确使用 CSCRIPT。混合方法使实用程序更加方便。

将其命名为 addtimes.bat 并像以前一样使用它。

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment

::************ Batch portion ***********
@echo off
cscript //E:JScript //nologo "%~f0"
exit /b 0

************* JScript portion **********/
while (!WScript.StdIn.AtEndOfStream) {
  var ts = new Date()
  var ms = (ts.getTime() % 1000)
  WScript.Stdout.WriteLine(
    ts.getFullYear() + "-" +
    ((ts.getMonth()<9)?"0":"") + (ts.getMonth()+1) + "-" +
    ((ts.getDate()<10)?"0":"") + ts.getDate() + " " +
    ((ts.getHours()<10)?"0":"") + ts.getHours() + ":" +
    ((ts.getMinutes()<10)?"0":"") + ts.getMinutes() + ":" +
    ((ts.getSeconds()<10)?"0":"") + ts.getSeconds() + "." +
    ((ms<10)?"00":((ms<100)?"0":"")) + ms + " - " +
    WScript.StdIn.ReadLine()
  );
}
Run Code Online (Sandbox Code Playgroud)


编辑

wmz 有一个非常聪明但危险的解决方案。该解决方案可以简化 - 无需使用自动运行。

警告 - 正如 wmz 所说,如果输出中的任何行以可执行命令或程序名称开头,下面的解决方案可能会产生非常糟糕的后果!我不建议实际使用这个解决方案,但我发现它非常有趣。

(echo @prompt $D $T -$S & YourCommandHere )|cmd 2>nul|findstr /rbc:"../../.... ..:..:..\... - " >log.log
Run Code Online (Sandbox Code Playgroud)

添加 FINDSTR 管道是为了去除 CMD 标头信息、初始 PROMPT 命令以及 CMD 在每个“命令”之后插入的不需要的空行。FINDSTR 正则表达式可能需要更改以匹配您选择的提示符和区域设置的具体信息。