echo \0x0A 时附加额外的 \x0D

echo \0x0A 时附加额外的 \x0D

我正在尝试将一些十六进制值发送到 tty 端口/dev/ttyS2。当我使用echoor 时,printf \x0A它会\x0D\x0A.

i=1 
a=$(printf "\xAA\xEE\x0A\x%02x" $i)
echo -ne   "$a"  > /dev/ttyS2

我在终端/串行端口上得到了这个——注意额外的 0D。我怎样才能删除它?

在此输入图像描述

答案1

如果您希望字节按原样通过串行连接双向传输,则需要告诉系统它不要用作终端设备,方法是从系统中分离 tty 线路规则或发出:

stty raw -echo < /dev/ttyS2

在您的情况下,正是onlcrtty 设备上默认启用的属性导致输出上的 LF 到 CRLF 转换。您可以禁用全部输出处理包括ocrnlwith stty -opost,但这留下了在另一个方向传输的数据的所有输入处理。

您没有指示您正在使用哪个 shellechoprintf实现,但请注意 ,-n选项-e不是标准的,并且参数包含的行为printf或何时的行为未指定。echo\x

printf其格式参数的几种实现扩展\xHH为值 0xHH 的字节。

在那些

printf "\xAA\xEE\x0A\x%02x" $i

将扩展\xAA为字节 0xAA,而 for\x会将其扩展为字节 0 或按\x字面意思或抱怨十六进制数字丢失。例如,你最终会得到<0xaa><0xee><LF>\x01in 。$a

有些echo实现也解释\xHH序列(有些仅在传递-e选项时)。

在这里,如果你想便携,你会这样做:

a=$(printf '\\252\\356\\012\\%03o' "$i")
printf "$a" > /dev/ttyS2

或者:

a=$(printf '\\0252\\0356\\0012\\0%03o' "$i")
printf %b "$a" > /dev/ttyS2

(标准printf支持\ooo格式中的八进制序列,以及一种%b旨在模拟某些echo实现使用或不使用 进行的扩展类型的格式-e,并且八进制序列表示为\0ooo)。

您还想确保第一个printf不输出 NUL 字节,因为除了 之外,shell 不能在其变量中存储 NUL 字节(例如zsh不要这样做)。a=$(printf '\0 or \x00 or \u0000')

zsh

bytes=(0xaa 0xee 0x0a $i)
set +o multibyte
printf %s ${(#)bytes} > /dev/ttyS2

该数据可以通过以下任一方式存储在变量中:

printf -v data %s ${(#)bytes}

或者

data=${(#j[])bytes}

但更一般地说,如果您想使用任意字节值操作数据,您可能需要使用适当的编程语言,即使它是像perl或 之 类的解释型语言python

另一种方法是使用类似的工具xxd可以在二进制形式和文本十六进制转储之间来回转换。

printf aaee0a%02d "$i" | xxd -p -r > /dev/ttyS1

答案2

您需要禁用换行符转换:

stty -F /dev/ttyS2 -onlcr

或者,对于严格的 POSIXstty:

stty -onlcr < /dev/ttyS2

相关内容