在bash脚本中将前导零添加到十六进制数

在bash脚本中将前导零添加到十六进制数,bash,awk,can-bus,bc,Bash,Awk,Can Bus,Bc,我正在做一个CAN总线项目,并试图发送一条消息来设置时间和日期。我已经计算出消息需要如何格式化,获取日期/时间并存储在变量中。我已经很好地将它们转换为十六进制,但是我需要将pad的前导0添加到消息所需的空间中 我尝试过在线上看到的bash脚本方法,但我遇到了一个问题: 2019年是以十六进制表示的7E3年。我需要这个显示为07E3。使用awk添加前导0时,E3被解释为工程符号*10^3,因此打印为7000。下面是我的脚本以及显示CAN总线消息格式的图像。感谢您的帮助 #!/bin/bash #

我正在做一个CAN总线项目,并试图发送一条消息来设置时间和日期。我已经计算出消息需要如何格式化,获取日期/时间并存储在变量中。我已经很好地将它们转换为十六进制,但是我需要将pad的前导0添加到消息所需的空间中

我尝试过在线上看到的bash脚本方法,但我遇到了一个问题: 2019年是以十六进制表示的7E3年。我需要这个显示为07E3。使用awk添加前导0时,E3被解释为工程符号*10^3,因此打印为7000。下面是我的脚本以及显示CAN总线消息格式的图像。感谢您的帮助

#!/bin/bash

#Store Date/Time in Variables
Year=`date '+%Y'`
Month=`date '+%m'`
Day=`date '+%d'`
Hour=`date '+%H'`
Minute=`date '+%M'`
Second=`date '+%S'`

#Convert Date/Time to Hexadecimel
HexYear=`echo "ibase=10;obase=16;$Year"| bc | awk '{ printf("%04d\n", $1) }'`
HexMonth=`echo "ibase=10;obase=16;$Month"| bc | awk '{ printf("%02d\n", $1) }'`
HexDay=`echo "ibase=10;obase=16;$Day"| bc | awk '{ printf("%02d\n", $1) }'`
HexHour=`echo "ibase=10;obase=16;$Hour"| bc | awk '{ printf("%02d\n", $1) }'`
HexMinute=`echo "ibase=10;obase=16;$Minute"| bc | awk '{ printf("%02d\n", $1) }'`
HexSecond=`echo "ibase=10;obase=16;$Second"| bc | awk '{ printf("%02d\n", $1) }'`

echo "The following is Decimel > Hex"
echo "$Year > $HexYear"
echo "$Month > $HexMonth"
echo "$Day > $HexDay"
echo "$Hour > $HexHour"
echo "$Minute > $HexMinute"
echo "$Second > $HexSecond"

所有的
echo | bc | awk
都可以归结为

$: HexYear=$( printf "%04X\n" $Year )
$: echo "$Year > $HexYear"
2019 > 07E3

X>X,因为它不要求将var声明为大写。

与其他
printf
格式一样,awk中的答案是
%0X
,例如:

$ echo 2019 01 04 | awk '{ printf("%02X%02X%04X\n", $2, $3, $1) }'
010407E3
x
表示十六进制,数字A-F的大小写与字母的大小写匹配,
0
表示前导零,之后可以指定所需的宽度(例如,填充四位数字,前导零为大写:
%04X

如果您不需要awk处理其他任何事情(例如处理多行),只需直接使用printf:

$ printf "%02X%02X%04X\n" `date '+%m %d %Y'`
010407E3

你必须意识到,当你可以调用
date
6次,然后调用
bc
+
awk
去做一些
awk
可以单独做的事情,然后再做6次时,调用
date
是多么的低效。花点时间真正思考一下你的脚本在做什么

date
加上任何awk查看此项:

$ awk -v dec="$(date '+%Y %m %d %H %M %S')" 'BEGIN {
    split(dec,a)
    hex = sprintf("%X %X %X %X %X %X",a[1],a[2],a[3],a[4],a[5],a[5])
    print dec, "->", hex
}'
2019 01 05 08 22 06 -> 7E3 1 5 8 16 16
或使用GNU awk进行时间功能:

$ awk 'BEGIN {
    dec = strftime("%Y %m %d %H %M %S") 
    split(dec,a)
    hex = sprintf("%X %X %X %X %X %X",a[1],a[2],a[3],a[4],a[5],a[5])
    print dec, "->", hex
}'
2019 01 05 08 18 54 -> 7E3 1 5 8 12 12
要将结果返回到shell中,请执行以下操作:

$ hex=( $(awk 'BEGIN{dec=strftime("%Y %m %d %H %M %S"); split(dec,a); hex=sprintf("%X %X %X %X %X %X",a[1],a[2],a[3],a[4],a[5],a[5]); print hex}') )
$ declare -p hex
declare -a hex=([0]="7E3" [1]="1" [2]="5" [3]="8" [4]="1F" [5]="1F")

我尝试了这种方法,但得到了以下响应:./DateSet.sh:line 13:declare:-u:invalid option declare:usage:declare[-afFirtx][p][name[=value]…]下面是Decimel>Hex 2019>01>01 04>04 22>16 55>37 35>23抱歉,我不知道为什么格式不正确。本文件打印为2019>(仅为空白)。不确定为什么。你的答案和下面的答案帮助解决了这个问题,谢谢。编辑-跳过了var的大写声明,支持使用X vs X。很抱歉你遇到了麻烦,不客气。谢谢你,这帮了我到达那里。将我的代码简化为:HexYear=$(printf“%04X\n”$Year)HexMonth=$(printf“%02X\n”$Month)谢谢您的建议。目前不担心效率低下,因为这只是我测试理论以确保它们是正确的。该项目将用python或C编写,这只是我测试的第一步。调用date 6次等,让我(一个人)立即明白代码的意图。人类也必须阅读代码,而且(hu)工时远比CPU工时昂贵。