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 函数,它使用 printfsedtac / 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