在文件内test.txt
我有一个十六进制值
0x0000000000000000000000000000000000000000047546124890225541102135415377465907
只有一行。没有其他线条或字符。它也仅由 0x 标识。
我想将这个十六进制值转换为十进制(388355321549592156970965297418600041568519
),减去 1,并用此操作的结果覆盖原始值test.txt
最终,文件中的数据test.txt
应该从
0x0000000000000000000000000000000000000000047546124890225541102135415377465907
到
388355321549592156970965297418600041568518
如果您能告诉我如何使用 Bash(Linux shell)执行此操作,我将不胜感激。
答案1
使用perl
,就地编辑文件:
perl -Mbigint -lpi -e '$_ = hex($_) - 1' your-file
假设整行都是十六进制数字。要转换所有十六进制数字,无论它们位于何处:
perl -Mbigint -lpi -e 's{\b0x[\da-f]+\b}{hex($&) - 1}gie' your-file
答案2
GNUawk
gawk -M '{print strtonum($0)-1}' file
-M
(或--bignum
) 用于任意精度算术。strtonum($0)
获取记录的数值,将字符串视为十六进制数字,因为它以 开头0x
。用于-i inplace
输入文件的就地编辑。
答案3
通过 bash 中的一个命令,使用这里的字符串和计算器(带有后缀表示法):
dc -e '16iAo?1-p' <<<$(<file) >file
16i
-输入基数
Ao
-输出基数
?
-读取一行
1-
-减一
p
-印刷
注意:您的示例中未指定。dc
计算器接受大写的十六进制数字 [ABCDEF]。
答案4
当问题询问文件中某处的十六进制数字时给出了这个答案。后来,问题被更新为整个文件仅由该数字组成。这个答案仍然有效,但当然你不会sed
在这种特殊情况下使用。我仍然把它留在这里,作为寻求原始问题答案的人的参考。还请注意评论。
如果您有bash
,您可能也有 GNU sed
(带有命令e
标志s
)。然后你还需要bc
计算器,因为你的数字太大了bash
:
sed 's/^0x0*\(.*\)/echo "ibase=16; \1-1"|bc/e' yourfile
- 我认为,以 开头的每一行都
0x
应该被转换,但是您可以轻松地调整它 0x0*\(.*\)
是要改变的模式。我们删除了前导0x
和多余的前导零,而其他所有内容都在 中,因此可以在替换中\(…\)
引用\1
echo "ibase=16; \1-1"|bc
e
是替换后shell要执行的shell命令- 实际计算是
\1-1
,即清理后的十六进制数减一。告诉这是一个十六进制ibase=16
数字bc