在 bash 脚本中将前导零添加到十六进制数
Adding leading zeros to a Hex number within bash script
我正在处理一个 CAN 总线项目,并尝试发送一条消息来设置时间和日期。我已经弄清楚消息需要如何格式化,抓取 date/time 并存储在变量中。我已经将它们转换为十六进制就好了,但是我需要添加前导 0 来填充消息所需的 space。
我试过网上看到的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", ) }'`
HexMonth=`echo "ibase=10;obase=16;$Month"| bc | awk '{ printf("%02d\n", ) }'`
HexDay=`echo "ibase=10;obase=16;$Day"| bc | awk '{ printf("%02d\n", ) }'`
HexHour=`echo "ibase=10;obase=16;$Hour"| bc | awk '{ printf("%02d\n", ) }'`
HexMinute=`echo "ibase=10;obase=16;$Minute"| bc | awk '{ printf("%02d\n", ) }'`
HexSecond=`echo "ibase=10;obase=16;$Second"| bc | awk '{ printf("%02d\n", ) }'`
echo "The following is Decimel > Hex"
echo "$Year > $HexYear"
echo "$Month > $HexMonth"
echo "$Day > $HexDay"
echo "$Hour > $HexHour"
echo "$Minute > $HexMinute"
echo "$Second > $HexSecond"
CAN bus message format
所有 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", , , ) }'
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
加上任何 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")
我正在处理一个 CAN 总线项目,并尝试发送一条消息来设置时间和日期。我已经弄清楚消息需要如何格式化,抓取 date/time 并存储在变量中。我已经将它们转换为十六进制就好了,但是我需要添加前导 0 来填充消息所需的 space。
我试过网上看到的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", ) }'`
HexMonth=`echo "ibase=10;obase=16;$Month"| bc | awk '{ printf("%02d\n", ) }'`
HexDay=`echo "ibase=10;obase=16;$Day"| bc | awk '{ printf("%02d\n", ) }'`
HexHour=`echo "ibase=10;obase=16;$Hour"| bc | awk '{ printf("%02d\n", ) }'`
HexMinute=`echo "ibase=10;obase=16;$Minute"| bc | awk '{ printf("%02d\n", ) }'`
HexSecond=`echo "ibase=10;obase=16;$Second"| bc | awk '{ printf("%02d\n", ) }'`
echo "The following is Decimel > Hex"
echo "$Year > $HexYear"
echo "$Month > $HexMonth"
echo "$Day > $HexDay"
echo "$Hour > $HexHour"
echo "$Minute > $HexMinute"
echo "$Second > $HexSecond"
CAN bus message format
所有 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", , , ) }'
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
加上任何 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")