我有一个 RFID 读取器,每次成功读取时,它都会将 RFID 标签的唯一 ID 发送到我的 Linux(树莓派)盒子的串行端口。问题是它发送时没有任何换行符。下面是输出的示例:
root@scalepi:~/scale# ./grabserial -d "/dev/ttyUSB4" -b 9600
$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#
我想用新行将每个条目写入文本文件,如下所示:
$A0112OKD9990001200005643E#
$A0112OKD9990001200005643E#
$A0112OKD9990001200005643E#
正如您所看到的,每个条目都以 $ 开头并以 # 结尾
我尝试使用此行将输出通过管道传输到 sed,在 # 之后添加新行,但输出为零,因为我认为 sed 在处理数据之前正在寻找新行:
./grabserial -d "/dev/ttyUSB4" -b 9600 | sed 's/#/#\r\n/g'
如果我将输出重定向到一个文件,然后 cat 该文件,通过相同的 sed 命令进行管道传输,我会得到我所期望的结果,但我需要能够以这种格式将数据写入文件,以便我可以读取它实时。
root@scalepi:~/scale# ./grabserial -d "/dev/ttyUSB4" -b 9600 > /tmp/test2.txt
^C
root@scalepi:~/scale# cat /tmp/test2.txt | sed 's/#/#\r\n/g'
$A0112OKD9990001200005643E#
$A0112OKD9990001200005643E#
$A0112OKD9990001200005643E#
root@scalepi:~/scale#
如果有人对我有任何建议,我将不胜感激。谢谢!
编辑-更新
尝试下面的“tr”解决方案后,我能够获得实时输出,但如果我尝试通过管道重定向,或通过 stdout/stderr 重定向,我一次会得到 50-60 行的缓冲结果,而不是得到逐行结果。
以下命令将在串行端口输入时为我提供实时输出:
./grabserial -d "/dev/ttyUSB4" -b 9600 | tr '#' '\n'
以下命令将一次给出 50 或 60 行块的输出(不是实时的):
./grabserial -d "/dev/ttyUSB4" -b 9600 | tr '#' '\n' | sed -u 's/$/#\r/g'
以下命令将一次将 50 或 60 行块输出到文本文件(不是实时):
./grabserial -d "/dev/ttyUSB4" -b 9600 | tr '#' '\n' > /tmp/test1.txt
FWIW,我使用 cat 读取串行端口而不是“grabserial”得到相同的结果。
以下命令给我实时结果:
cat /dev/ttyUSB4 | tr '#' '\n'
但是,当我尝试通过管道或标准输出重定向来重定向输出时,我在文本文件中得到缓冲的数据块:
cat /dev/ttyUSB4 | tr '#' '\n' > /tmp/test4.txt
答案1
您可以将#
字符翻译(或音译)为换行符
tr '#' '\n'
所以
./grabserial -d "/dev/ttyUSB4" -b 9600 | tr '#' '\n'
应该给你
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
︙
实时。如果你需要英镑符号和/或回车符,您可以将以上内容通过管道传输到
… sed 's/$/#\r/'
(使用sed
(以及一般的正则表达式)用于$
表示行尾的事实。
陷阱
tr
当输出进入管道或文件时,您可能会遇到缓冲其输出的问题。也许处理这个问题的最好方法是遵循阿尔法的建议
关闭缓冲stdbuf
;例如,
./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' | sed 's/$/#\r/' > RFIDs.txt
如果不清楚,选项stdbuf
是小写o
(oh) 和大写L
(ell),这表示标准输出应该是行缓冲的。
底线(TL;DR)#1:
所以你应该能够使用
./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' > RFIDs.txt
获取#
末尾没有 的条目,或者
./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' | sed 's/$/#/' > RFIDs.txt
获取#
末尾带有 ,但不带有\r
, 或 的条目
./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' | sed 's/$/#\r/' > RFIDs.txt
获取条目#
和的\r
在最后。
底线(TL;DR)#2:
你还没有说你如何终止命令。如果您输入Ctrl+ C,则可能造成问题1 .如果是这样,请尝试:
- 使用 , 将上述命令行之一放入后台
&
,然后 - 当你准备退出时,执行 a
ps
并获取进程的 PIDgrabserial
,然后 - 用命令杀死它
kill
。
底线(TL;DR)#3:
您说您需要能够实时读取数据,但无需详细说明。如果您有一些能够从标准输入读取的程序/脚本,请尝试
./grabserial -d“/dev/ttyUSB4”-b 9600 | stdbuf -oL tr '#' '\n' | stdbuf -oL tr '#' '\n' | stdbuf -oL tr '#' '\n' | sed 's/$/#\r/'| T 恤 RFIDs.txt | 你的程序
这应该将数据写入输出文件,同时将其传输到您的程序。
底线(TL;DR)#4:
事实上,如果cat
和 一样有效grabserial
,那么您实际上不需要其中任何一个;像
stdbuf -oL tr '#' '\n' < /dev/ttyUSB4 | sed 's/$/#\r/' > RFIDs.txt
应该也能正常工作。
____________
1根据您的更新,这可能不是您的问题,但我将其留在这里,以防对其他人有帮助。
请注意,tr
基本上是在一对一的基础上运行的。 (有一些选项可以做一些稍微花哨的事情。)所以,例如,
tr 'abc…' 'ABC…'
将替换a
为A
、 b
with B
、 c
withC
等。所以你不能做类似的事情
tr '#' '#\r\n'