【问题标题】:awk output into BC HexToDec calculationawk 输出到 BC Hex To Dec 计算器
【发布时间】:2018-02-12 14:05:58
【问题描述】:

我正在尝试组合 awkbc 以创建一个 bash 函数,用于将十六进制值快速转换为适当的格式。

echo FFFFFF | VAR=$(awk '{print toupper($0)}') | "ibase=16; $((((($VAR - 5) / 100) - 1000)))" | bc

我正在尝试这个,但我似乎无法将 awk 的输出输入到 bc 参数的输入中。

【问题讨论】:

  • 请提供给定输入的预期输出,因为我们不知道您是要尝试减去十进制 100 还是十六进制 100 或做其他任何事情。
  • 我看到 you've asked 10 questions 并且到目前为止只接受了 1 个答案。如果没有任何答案对您有帮助,请阅读stackoverflow.com/help/someone-answers 或作为 cmets 提供反馈。

标签: bash awk bc


【解决方案1】:

虽然您尝试使用awkbc 来实现,但我在这里为您提供最方便的选择:printf。这使您可以轻松地在十进制、八进制和十六进制之间进行转换。

[bash] % printf "%d" 0xFFFFFF    # hex2dec
16777215
[bash] % printf "%#O" 0xFFFFFF   # hex2oct
077777777
[bash] % printf "%d" 077777777   # oct2dec
16777215
[bash] % printf "%d" 077777777   # oct2hex
0xFFFFFF
[bash] % printf "%#x" 16777215   # dec2hex
0xFFFFFF
[bash] % printf "%#O" 16777215   # dec2oct
077777777

额外的字符 # 要求 printf 插入前缀 0X 用于十六进制数字,0 用于八进制数字。如果您以十六进制形式添加数字,请不要忘记为数字添加前缀0x,并为八进制数字添加前缀0

当然bash 可以选择进行算术运算。

man bash((expression)) 表达式根据下面算术评估中描述的规则进行评估。如果表达式的值非零,则返回状态为0;否则返回状态为1。这完全等同于let "expression"

这使您可以直接进行所有计算。例如。你想要 0xFFFFFF 并减去小数 5 并除以 100(十进制)并减去 1000 小数,你有

[bash] % printf "%d" $(( (0xFFFFFF - 5)/100 - 1000 ))
166772

或者你可以全部使用十六进制::

[bash] % printf "%d" $(( (0xFFFFFF - 0x5)/0x100 - 0x1000 ))
61439

如果您现在想将这样的数字存储在变量中,您只需这样做

[bash] % vardec=$( printf "%d" $(( (0xFFFFFF - 0x5)/0x100 - 0x1000 )) )
[bash] % varhex=$( printf "%#x" $(( (0xFFFFFF - 0x5)/0x100 - 0x1000 )) )
[bash] % varoct=$( printf "%#O" $(( (0xFFFFFF - 0x5)/0x100 - 0x1000 )) )

但是,十进制是一种特殊情况,您可以去掉printf

[bash] % vardec=$(( (0xFFFFFF - 0x5)/0x100 - 0x1000 ))

bash 的算术评估系统允许您以任何基数(最高为基数 64)写入任何数字,并将其转换为十进制。在这里,我将一个基数为 3 的数字 3#1212 转换为数字 50。

[bash] % echo $(( 3#1212 ))
50

如果您想使用 zsh,您可以转换回任何其他基础:

[zsh] % echo $(( [##2]7 ))            # from base 10 to base 2
111
[zsh] % echo $(( [##5]3#1020101100 )) # from base 3 to base 5
1234321
[zsh] % echo $(( [##36]17#415C67A8 )) # from base 17 to base 36
ROFLOL

【讨论】:

  • 感谢这确实提供了最简单的 printf 方法。
【解决方案2】:

试试

 echo FFFFFF |
 awk '{printf "ibase=16\n(((((%s - 5) / 100) - 1000)))\n",toupper($1) ;}' |
 bc

(这个可以上网,确保|是最后一个字符)

在原始脚本中

echo FFFFFF | VAR=$(awk '{print toupper($0)}') 
  • awk 没有输入,VAR 为空

    "ibase=16; $((((($VAR - 5) / 100) - 1000)))"
    
  • "ibase=... " 是一个命令,这不是你想要的,它什么也不输出(保存错误)。

更复杂的公式

VAR=$(echo FFFFFF | tr [:lower:] [:upper:])
VAR2=..
VARx=...
bc <<EOF
ibase=16
((($VAR - 5) / $VAR2) - $VARx)
EOF

在哪里

  • bc &lt;&lt;EOF 被称为heredoc 变量,在运行时会被删除。

【讨论】:

  • Archemar - toUpper 用于确保 HEX 输入在进入 BC 之前全部为大写,否则输出将不正确。您提供的内容没有给出正确的结果
  • 好吧,awktr 版本不正确吗? tr 版本可能会出错,如果您有任何文件名是上或下的子集,在这种情况下,将tr 替换为awk
  • @AdamBen-David echo 'ibase=16; (((FFFFFF - 5) / 100) - 1000)' | bc 是否为您提供“正确的结果”?如果没有,请先调试它,暂时不要担心通过 awk 的管道。
  • 它给了我 61439。
  • @Archemar 和 ibase=16 您明确告诉 bc 将所有数字视为十六进制,就像 fffff 是十六进制(十进制 = 16777215)一样,100 也是如此(十进制 = 256) 和 1000 (4096) 同上,因此 61439 是该脚本的一个可能的正确输出(另一个是 61440,取决于使用的舍入,因为浮点结果实际上是 61439.976562)。
【解决方案3】:

您没有提供任何示例输入或预期输出,但这是您想要做的吗?

$ echo FFFFFF | awk '{print strtonum("0x"$0)}'
16777215

$  echo FFFFFF | awk '{print ((strtonum("0x"$0) - 5) / 100) - 1000}'
166772

以上使用 GNU awk for strtonum() 将非十进制字符串转换为数值,大小写无关:

$  echo ffffff | awk '{print ((strtonum("0x"$0) - 5) / 100) - 1000}'
166772

或者您的“100”等也可能是十六进制的?

$ echo FFFFFF | awk '{print ((strtonum("0x"$0) - strtonum("0x5")) / strtonum("0x100")) - strtonum("0x1000")}'
61440

请注意,计算结果实际上是一个浮点数,因此在将其打印为整数时会在上面进行舍入:

$ echo FFFFFF | awk '{printf "%f\n", ((strtonum("0x"$0) - strtonum("0x5")) / strtonum("0x100")) - strtonum("0x1000")}'
61439.976562

附:我开始为此使用 gawk-only -n 选项,但实际上应该避免使用 strtonum(),请参阅 https://www.gnu.org/software/gawk/manual/gawk.html#Nondecimal-Data

【讨论】:

    猜你喜欢
    • 2012-12-19
    • 2015-06-21
    • 2016-06-10
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 2012-07-26
    • 2016-11-07
    • 2020-09-12
    相关资源
    最近更新 更多