我可以/如何将命令输出的每行传输到另一个命令(在Windows上)。
例如,我有tshark
输出:
1 0.000000 1.1.1.1 -> 1.1.1.2 TLSv1.2 85 Application Data
2 0.000726 1.1.1.2 -> 1.1.1.1 TLSv1.2 89 Application Data
3 0.064803 1.1.1.3 -> 1.1.1.2 TLSv1 155 Application Data
4 0.155403 1.1.1.1 -> 1.1.1.2 TCP 60 443â┼'62745 [ACK] Seq=32 Ack=36 Win=374 Len=0
5 0.268586 1.1.1.2 -> 1.1.1.3 TCP 54 56149â┼'443 [ACK] Seq=1 Ack=102 Win=63331 Len=0
6 0.730557 1.1.1.2 -> 1.1.1.4 UDP 45 Source port: 46586 Destination port: 52531
7 1.069927 1.1.1.5 -> 1.1.1.2 TCP 60 40020â┼'50293 [PSH, ACK] Seq=1 Ack=1 Win=136 Len=3
8 1.179893 fe00::dd00:9f00:dd00:1e00 -> ff00::c SSDP 208 M-SEARCH * HTTP/1.1
9 1.269580 1.1.1.2 -> 1.1.1.5 TCP 54 50293â┼'40020 [ACK] Seq=1 Ack=4 Win=16130 Len=0
我想在每一行执行my-prog.bat
,例如:
my-prog.exe 1 0.000000 1.1.1.1 -> 1.1.1.2 TLSv1.2 85 Application Data
my-prog.exe 2 0.000726 1.1.1.2 -> 1.1.1.1 TLSv1.2 89 Application Data
my-prog.exe 3 0.064803 1.1.1.3 -> 1.1.1.2 TLSv1 155 Application Data
my-prog.exe 4 0.155403 1.1.1.1 -> 1.1.1.2 TCP 60 443â┼'62745 [ACK] Seq=32 Ack=36 Win=374 Len=0
my-prog.exe 5 0.268586 1.1.1.2 -> 1.1.1.3 TCP 54 56149â┼'443 [ACK] Seq=1 Ack=102 Win=63331 Len=0
my-prog.exe 6 0.730557 1.1.1.2 -> 1.1.1.4 UDP 45 Source port: 46586 Destination port: 52531
my-prog.exe 7 1.069927 1.1.1.5 -> 1.1.1.2 TCP 60 40020â┼'50293 [PSH, ACK] Seq=1 Ack=1 Win=136 Len=3
my-prog.exe 8 1.179893 fe00::dd00:9f00:dd00:1e00 -> ff00::c SSDP 208 M-SEARCH * HTTP/1.1
my-prog.exe 9 1.269580 1.1.1.2 -> 1.1.1.5 TCP 54 50293â┼'40020 [ACK] Seq=1 Ack=4 Win=16130 Len=0
我的my-prog.bat
只是echo %TIME% %* >> test.txt
我尝试过一些事情(使用GnuWin xargs):
tshark | xargs my-prog.bat
tshark | xargs -n1 my-prog.bat
但我得到的最好的是将%*
输出到文件中。 (my-prog.bat test
按预期工作,并将test
追加到文件中
(注意tshark
将继续运行,直到按下CTRL + C)
答案 0 :(得分:2)
首先验证tshark将其输出发送到stdout。如果你运行tshark >nul
并且没有输出,那么确实使用了stdout,一切都很好。
如果您仍然看到输出,请使用tshark 2>nul
尝试使用stderr。如果这消除了输出,则必须使用tshark 2>&1
将stderr重定向到stdout。
如果以上两种方法都没有消除屏幕上的输出,那么你就不走运了。
现在,您希望将输出通过管道传输到批处理脚本,该脚本将为每行输出添加时间戳前缀。有许多并发症:
输出包含>
字符,当您调用批处理脚本时,该字符被解释为重定向操作。需要引用或转义违规字符。逃避是一种痛苦,引用会为你的最终输出添加不需要的引号。
您需要按<Ctrl-C>
来终止tshark进程,但是会终止管道的两侧,如果要终止批处理脚本,右侧会提示,但是没有更多输入 - 它挂起
在我的原始答案中,我认为你可以消除管道并通过FOR / F处理线路。但是FOR / F在命令完成之前不会开始迭代,因此无法工作。
我提出的最佳解决方案是在管道的右侧使用JScript(或VBS可以工作)来添加时间戳前缀。
假设您的左侧从未提示输入而不发出新行,那么您可以使用:
<强> addTS.js 强>
while( !WScript.StdIn.AtEndOfStream ) {
var time = new Date;
WScript.StdOut.WriteLine( zpad(time.getHours(),2) + ":"
+ zpad(time.getMinutes(),2) + ":"
+ zpad(time.getSeconds(),2) + '.'
+ zpad(time.getMilliseconds(),3) + " "
+ WScript.StdIn.ReadLine()
);
}
function zpad(num, size) {
var s = "000" + num;
return s.substr(s.length-size);
}
<强> 用法: 强>
tshark|cscript //nologo addTS.js
如果您的左侧在没有发出新行的情况下要求输入,那么在您提供输入之前,您将无法看到提示。这并不好用。所以这是addTS.js的修改版本,它可以单独读取和写入每个字符:
var time, chr, newLine=true;
while( !WScript.StdIn.AtEndOfStream ) {
chr=WScript.StdIn.Read(1);
if (newLine) {
time = new Date();
WScript.StdOut.Write( zpad(time.getHours(),2) + ":"
+ zpad(time.getMinutes(),2) + ":"
+ zpad(time.getSeconds(),2) + '.'
+ zpad(time.getMilliseconds(),3) + " "
);
newLine=false;
}
WScript.StdOut.Write(chr);
newLine=(chr=='\n');
}
function zpad(num, size) {
var s = "000" + num;
return s.substr(s.length-size);
}
答案 1 :(得分:1)
你为什么不这样做:
for /f "delims=" %%a in ('tshark') do (my-prog.bat %%a)
这正是你想要的。
注意:这适用于批处理文件。如果您想直接在命令提示符中执行此操作,则必须将%%a
替换为%a
我刚刚注意到,最终结果是有一个日志文件,其中包含来自tshark
的数据。如果是这种情况你可以:
tshark > test.txt
与调用my-prog.bat
的结果相同,它也会逐行执行,因此您可以无限期地运行它。我已经在我的计算机上测试了它(在dir /s > test.txt
中运行C:
并且当它运行type test.txt
时,虽然命令还没有完成,但已经有线路了。“ / p>