Awk,小端顺序和 4 个十六进制数字
Awk, little endian order and 4 hex digits
我想我有一个十进制数,例如 97254 ---> 00017BE6(十六进制值)使用:
echo "" | awk '{printf("%08X", 97254)}'
现在,如果我想将十六进制数(在本例中为 00017BE6)转换为小端顺序和 CSV 格式的 4 个 2 位数字(输入中最多 8 个数字),即(target ):
E6,7B,01,00
using only awk(一个函数ad-hoc和return值,例如),怎么办?
有:
awk '{for (i=1;i<=7;i=i+2) array[i]=substr(,i,2)} END{for(a in array) print array[a]}'
我有:
00
01
7B
E6
使用:
awk '{for (i=1;i<=7;i=i+2) array[i]=substr(,i,2)} END{for(a in array) print array[a]}' ORS=","
我有:
00,01,7B,E6,
但是如何删除最后一个逗号并将其转换为小端顺序?
我该怎么做?
有什么想法吗?
echo 00017BE6 | awk '{for (i=7;i>=1;i=i-2) printf "%s%s",substr(,i,2),(i>1?",":"\n")}'
E6,7B,01,00
使用sprintf
,我们可以从十进制数开始:
$ echo 97254 | awk '{hex=sprintf("%08X",); for (i=7;i>=1;i=i-2) printf "%s%s",substr(hex,i,2),(i>1?",":"\n");}'
E6,7B,01,00
工作原理
for (i=7;i>=1;i=i-2)
这会启动索引 i
的循环,我们在其中 down 从 7 数到 1。
printf "%s%s",substr(,i,2),(i>1?",":"\n")
这将打印所需的子字符串,后跟逗号或换行符。构造 i>1?",":"\n"
是 awk 的三元语句形式。它 returns ,
如果 i>1
否则换行。
您要求 awk
命令,但请考虑这个通用 bash
函数,它使用 printf
、sed
和 tac
/ tail -r
在内部,并在 BSD(包括 OSX)和 Linux 系统上工作:
# SYNOPSIS
# toHexBytes num [numBytes [littleEndian]]
# DESCRIPTION
# Prints the bytes that num is composed of in hex. format separated by commas.
# NUM can be in decimal, hexadecimal, or octal format.
# NUMBYTES specifies the minimum number of *bytes* to output - defaults to *4*.
# Specify 0 to only output as many bytes as needed to represent NUM, '' to
# represent the default when also specifying LITTLEENDIAN.
# By default, the bytes are printed in BIG-endian order; if LITTLEENDIAN is nonzero,
# the bytes are printed in LITTLE-endian order.
# PLATFORM SUPPORT
# BSD and Linux platforms
# EXAMPLES
# toHexBytes 256 # -> '00,00,01,00'
# toHexBytes 256 '' 1 # -> '00,01,00,00'
# toHexBytes 0x100 0 # -> '01,00'
toHexBytes() {
local numIn= numBytes=${2:-4} littleEndian=${3:-0} numHex revCmd
# Convert to hex.
printf -v numHex '%X' "$numIn"
# Determine number of 0s that must be prepended.
padCount=$(( numBytes * 2 - ${#numHex} ))
(( padCount < 0 && ${#numHex} % 2 )) && padCount=1
# Apply 0-padding, if needed.
(( padCount )) && printf -v numHex "%0$(( padCount + ${#numHex} ))X" "0x$numHex"
if (( $littleEndian )); then # LITTLE-endianness
# Determine command to use for reversing lines.
[[ $(command -v tac) ]] && revCmd='tac' || revCmd='tail -r'
# Insert a newline after every 2 digits, except for the last,
# then reverse the resulting lines,
# then read all resulting lines and replace all but the last newline
# with ','.
sed 's/../&\'$'\n''/g; s/\n$//' <<<"$numHex" |
$revCmd |
sed -e ':a' -e '$!{N;ba' -e '}; s/\n/,/g'
else # BIG-endianness
# Insert ',' after every 2 digits, except for the last pair.
sed 's/../&,/g; s/,$//' <<<"$numHex"
fi
}
应用于您的示例编号:
$ toHexBytes 97254 4 1 # 4 bytes, LITTLE-endian
E6,7B,01,00
$ toHexBytes 97254 # 4 bytes, BIG-endian
00,01,7B,E6
我想我有一个十进制数,例如 97254 ---> 00017BE6(十六进制值)使用:
echo "" | awk '{printf("%08X", 97254)}'
现在,如果我想将十六进制数(在本例中为 00017BE6)转换为小端顺序和 CSV 格式的 4 个 2 位数字(输入中最多 8 个数字),即(target ):
E6,7B,01,00
using only awk(一个函数ad-hoc和return值,例如),怎么办?
有:
awk '{for (i=1;i<=7;i=i+2) array[i]=substr(,i,2)} END{for(a in array) print array[a]}'
我有:
00
01
7B
E6
使用:
awk '{for (i=1;i<=7;i=i+2) array[i]=substr(,i,2)} END{for(a in array) print array[a]}' ORS=","
我有:
00,01,7B,E6,
但是如何删除最后一个逗号并将其转换为小端顺序?
我该怎么做?
有什么想法吗?
echo 00017BE6 | awk '{for (i=7;i>=1;i=i-2) printf "%s%s",substr(,i,2),(i>1?",":"\n")}'
E6,7B,01,00
使用sprintf
,我们可以从十进制数开始:
$ echo 97254 | awk '{hex=sprintf("%08X",); for (i=7;i>=1;i=i-2) printf "%s%s",substr(hex,i,2),(i>1?",":"\n");}'
E6,7B,01,00
工作原理
for (i=7;i>=1;i=i-2)
这会启动索引
i
的循环,我们在其中 down 从 7 数到 1。printf "%s%s",substr(,i,2),(i>1?",":"\n")
这将打印所需的子字符串,后跟逗号或换行符。构造
i>1?",":"\n"
是 awk 的三元语句形式。它 returns,
如果i>1
否则换行。
您要求 awk
命令,但请考虑这个通用 bash
函数,它使用 printf
、sed
和 tac
/ tail -r
在内部,并在 BSD(包括 OSX)和 Linux 系统上工作:
# SYNOPSIS
# toHexBytes num [numBytes [littleEndian]]
# DESCRIPTION
# Prints the bytes that num is composed of in hex. format separated by commas.
# NUM can be in decimal, hexadecimal, or octal format.
# NUMBYTES specifies the minimum number of *bytes* to output - defaults to *4*.
# Specify 0 to only output as many bytes as needed to represent NUM, '' to
# represent the default when also specifying LITTLEENDIAN.
# By default, the bytes are printed in BIG-endian order; if LITTLEENDIAN is nonzero,
# the bytes are printed in LITTLE-endian order.
# PLATFORM SUPPORT
# BSD and Linux platforms
# EXAMPLES
# toHexBytes 256 # -> '00,00,01,00'
# toHexBytes 256 '' 1 # -> '00,01,00,00'
# toHexBytes 0x100 0 # -> '01,00'
toHexBytes() {
local numIn= numBytes=${2:-4} littleEndian=${3:-0} numHex revCmd
# Convert to hex.
printf -v numHex '%X' "$numIn"
# Determine number of 0s that must be prepended.
padCount=$(( numBytes * 2 - ${#numHex} ))
(( padCount < 0 && ${#numHex} % 2 )) && padCount=1
# Apply 0-padding, if needed.
(( padCount )) && printf -v numHex "%0$(( padCount + ${#numHex} ))X" "0x$numHex"
if (( $littleEndian )); then # LITTLE-endianness
# Determine command to use for reversing lines.
[[ $(command -v tac) ]] && revCmd='tac' || revCmd='tail -r'
# Insert a newline after every 2 digits, except for the last,
# then reverse the resulting lines,
# then read all resulting lines and replace all but the last newline
# with ','.
sed 's/../&\'$'\n''/g; s/\n$//' <<<"$numHex" |
$revCmd |
sed -e ':a' -e '$!{N;ba' -e '}; s/\n/,/g'
else # BIG-endianness
# Insert ',' after every 2 digits, except for the last pair.
sed 's/../&,/g; s/,$//' <<<"$numHex"
fi
}
应用于您的示例编号:
$ toHexBytes 97254 4 1 # 4 bytes, LITTLE-endian
E6,7B,01,00
$ toHexBytes 97254 # 4 bytes, BIG-endian
00,01,7B,E6