Bash 将stdout重定向到脚本,以便可以对其进行分析,然后将其发送到stdout

Bash 将stdout重定向到脚本,以便可以对其进行分析,然后将其发送到stdout,bash,redirect,stdout,pipe,Bash,Redirect,Stdout,Pipe,我有一个(java)程序,每5秒打印一行十六进制数到标准输出,直到程序被用户终止 我想将输出重定向到bash脚本,这样我就可以将每个十六进制数独立地转换为十进制数,然后将解析后的行打印到stdout 我试着使用myProgram | myScript,但在打印任何行之前都会进行管道处理,然后就没有继续听stdout了。然后我尝试了myProgram>myScript,这只是重写了脚本 想法 编辑:从运行中添加输出(很抱歉格式不好,我无法在代码高亮显示中获得所有内容),因此输出的中间部分没有高亮显

我有一个(java)程序,每5秒打印一行十六进制数到标准输出,直到程序被用户终止

我想将输出重定向到bash脚本,这样我就可以将每个十六进制数独立地转换为十进制数,然后将解析后的行打印到stdout

我试着使用myProgram | myScript,但在打印任何行之前都会进行管道处理,然后就没有继续听stdout了。然后我尝试了myProgram>myScript,这只是重写了脚本

想法

编辑:从运行中添加输出(很抱歉格式不好,我无法在代码高亮显示中获得所有内容),因此输出的中间部分没有高亮显示)

这是剧本

#!/bin/bash
echo $0
echo $#
echo $1
下面是我的程序在直接进入标准输出时的运行方式,如果我不终止它,它将永远持续下去

mmmm@mmmm:~/mmmm/mmmm/mmmmm$ java net.tinyos.tools.Listen -comm 
serial@/dev/ttyUSB0:micaz
serial@/dev/ttyUSB0:57600: resynchronising   
00 FF FF 00 02 04 22 93 00 02 02 C9
00 FF FF 00 03 04 22 93 00 03 03 0E
00 FF FF 00 02 04 22 93 00 03 03 0E
00 FF FF 00 02 04 22 93 00 02 02 C9
^Z
[5]+  Stopped                 java net.tinyos.tools.Listen -comm          
serial@/dev/ttyUSB0:micaz
这里是我尝试将它导入脚本的地方(我已设置为打印命令行参数的数量和第一个参数。在此之后它将冻结

mmmm@mmmm:~/mmmm/mmmm/mmmmm$$ java net.tinyos.tools.Listen -comm serial@/dev/ttyUSB0:micaz | ./parser.sh
./parser.sh
0
serial@/dev/ttyUSB0:57600: resynchronising

\1.检查您的系统是否安装了unbuffer命令

    which unbuffer
(通常使用
bash
的系统是基于Linux的,并且有
unbuffer
可用)

\2.如果是

    unbuffer myProgram | myScript
编辑

正如您向我们展示的shell脚本一样

#!/bin/bash
echo $0
echo $#
echo $1
请记住,您要回显的值,
$0、$#、$1
是bash的位置参数,与命令行参数相关。通常是用于处理的选项或文件名

要打印整行、行上字段的#和第一行的值,awk是解决此问题的完美方法

尝试将脚本更改为

cat myScript.awk
#!/bin/awk -f
{ 
   print $0
   print $NF
   print $1
}

chmod 755 myScript.awk
嗯..看到
^Z
停止输入告诉我你在使用Windows还是在Cygwin下使用bash


我希望这会有所帮助。

这可能是一个缓冲问题。GNU Coreutils附带了一个名为
stdbuf
的工具。如果您的系统上有此工具,请尝试运行:

stdbuf -o0 program | stdbuf -i0 script
诊断 当您像这样使用此脚本时:

java javaprog | myScript
myScript
包含:

#!/bin/bash
echo $0
echo $#
echo $1
然后,脚本的输出将是
echo$0
中的名称(
myScript
),从
echo$#
中传递的参数数(0),以及从
echo$1
中返回的第一个参数(空行)。然后脚本退出(成功)。问题与缓冲无关;这与脚本没有从其标准输入中读取任何内容有关。即使是一个微不足道的修改也将是一个改进:

#!/bin/bash
while read data; do echo $data; done
这是一种较慢的
cat
,只是它将空格和制表符的随机序列规范化为单个空格,将前导空格和尾随空格从行中剥离。它至少可以演示处理Java程序输出的脚本


正在尝试
awk
要完成您所追求的目标,您可能应该使用
awk
程序或类似的程序来替换它。这是初稿,但它有一定的工作机会:

awk '{for(i = 1; i <= NF; i++) { x = "0x" $i + 0; printf(" %d", x); printf "\n";}'
这是可行的-甚至很容易理解。
-n
选项意味着“读取每行数据并在每行上执行脚本中的命令(但不要在末尾打印
$)。
-a
选项与
-n
(如此处所示,或
-p
-n
类似,只是它自动打印
$\u
)表示“自动将输入分割到数组
@F
。然后脚本使用
十六进制
函数转换
$F[$i]中的字符串,对每行
@F
中的每个元素进行处理(相当详细)
到一个数字,然后用
printf()打印该数字。
可以通过以下方法减少详细程度(这是Perl:有多种方法,或TMTOWTDI-tim toady):


同样的结果,更少的代码。可能会有更多的缩写技术;这足够紧凑而不会完全难以辨认。

您确定输出是标准输出,而不是标准错误吗?运行
myProgram>/tmp/out 2>/tmp/err
并发现哪个输出到哪个文件--
/tmp/out
,以获得标准输出,标准错误为
/tmp/err
。听起来您没有显式刷新stdout,当它未连接到tty时,它会自动停止工作。@sarnold我已使用您的示例确认程序发送到stdout@cnicutar我不知道你的意思是什么?但是我没有我正在使用的程序的源代码,所以我不能改变它。啊,一个Java程序。Java的标准库将执行它自己的缓冲,这就是为什么下面建议的
stdbuf
答案(以及使用
unbuffer
程序的类似建议)不起作用的原因。@我想我的系统上没有安装unbuffer(Ubuntu 11.10),但我可以用expect dev软件包安装它,这是我应该做的吗?@Michael:请看我对你的问题的评论末尾的评论+++请不要修改这个评论+++很难说肯定。这可能会有帮助,但在你的
myProgram
如何处理其输出方面可能还有其他问题。我不反对vinced这是一个java输出问题(本身),但更多的是关于缓冲区没有在正确的时间刷新。不确定,但我认为unbuffer会有帮助,即使是java程序。java大师?有什么经验可以分享吗?祝大家好运。@感谢您修复了我问题中的代码格式。我使用的是Ubuntu11.10。我之所以让脚本如此简单,只是因为我想要一些东西每次向脚本发送一行时,我都要打印(任何内容)。我最终要做的是删除十六进制集合的集合1-4和6-9,然后将最后两个集合转换为一个十进制数。我尝试了你的脚本,但无法运行。我尝试了以下命令(在chm之后)
$ echo '00 C9 28 13 A0 FF 01' |
> perl -na -e 'for ($i = 0; $i < scalar(@F); $i++) { printf(" %d", hex $F[$i]); }
>       printf "\n";'
 0 201 40 19 160 255 1
$
$ echo '00 C9 28 13 A0 FF 01' |
> perl -na -e 'foreach my $i (@F) { printf(" %d", hex $i); } printf "\n";'
 0 201 40 19 160 255 1
$