bash 生成特定范围的十六进制数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5517500/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:43:41  来源:igfitidea点击:

Generating hex numbers of a certain range

bashshellhex

提问by Dave

I need a simple way to generate a .txt file with a list of semi-colon delimited hex numbers between (inclusive) a certain start and finish value.

我需要一种简单的方法来生成一个 .txt 文件,其中包含(包含)某个起始值和结束值之间的以分号分隔的十六进制数列表。

For example:

例如:

If I enter 0and FFFit would pad the output with zeroes to the largest number:

如果我输入0FFF它将用零填充输出到最大数字:

000;001;002;003;004;005;006;007;008;009;00A;00B;00C;00D;00E;00F;010;011;....FFF;

000;001;002;003;004;005;006;007;008;009;00A;00B;00C;00D;00E;00F;010;011;...FFF;

If I enter FFFand 1200it would output those values...etc:

如果我输入FFF1200它会输出这些值...等等:

0FFF;1000;1001;1002;.....1200;

0FFF;1000;1001;1002;.....1200;

Any suggestions? I'm not a programmer so the best, simplest way to do this is way beyond me.

有什么建议?我不是程序员,所以最好、最简单的方法超出了我的范围。

回答by Jens

Here's a script that's portable (any POSIX shell will do), should work blazingly fast (no forks to nawk, bc, etc...) and adheres to the poster's spec.

这是一个可移植的脚本(任何 POSIX shell 都可以),应该工作得非常快(没有对 nawk、bc 等的分叉)并且符合海报的规范。

#!/bin/sh
#
# hexcount -  POSIX Shell script to count from  to  in hex,
#             separated by ";" and with the precision set to the
#             maximum digits of  and .
# Usage:      hexcount lo hi
# Example:    hexcount FFF 1200

from= to=
if test "${#from}" -gt "${#to}"; then
    format="%0${#from}X;"
else
    format="%0${#to}X;"
fi
from=$(printf '%d' "0x$from") to=$(printf '%d' "0x$to")
while test "$from" -le "$to"; do
    printf "$format" "$from"
    from=$((from+1))
done
printf '\n'

Ain't printf cool?

printf 是不是很酷?

回答by mcau

Another Attempt (still needs seq but not bc) - works in cygwin and linux:

另一种尝试(仍然需要 seq 但不需要 bc) - 适用于 cygwin 和 linux:

seq 0 255 | while read n; do printf "%04X;" $n; done

The inputs are decimal, but the output is capitalised hex and you can change the digits to show by updating the "04" part of the printf format string

输入是十进制,但输出是大写的十六进制,您可以通过更新 printf 格式字符串的“04”部分来更改要显示的数字

回答by William Cates

I just like to use simple for loops. You can add as many nested loops as you like for each digit:

我只是喜欢使用简单的 for 循环。您可以为每个数字添加任意数量的嵌套循环:

for i in {0..9} {a..f}; do for x in {0..9} {a..f}; do for y in {0..9} {a..f}; do printf "$i$x$y;"; done; done; done

Output should look like this:

输出应如下所示:

000;001;002;003;004;005;006;007;008;009;00a;00b;00c;00d;00e;00f;010;011;012;013;014;015;016;017;018...ff8;ff9;ffa;ffb;ffc;ffd;ffe;fff;

That was a one-liner, but let me give it some structure:

那是一个单行,但让我给它一些结构:

for i in {0..9} {a..f}
do
   for x in {0..9} {a..f}
   do
      for y in {0..9} {a..f}
      do
         printf "$i$x$y;"
      done
   done
done

回答by chuckx

Here's an implementation tested in KSH on OpenBSD (should work with any Bourne shell, doesn't rely on bashfeatures).

这是在 OpenBSD 上的 KSH 中测试的一个实现(应该适用于任何 Bourne shell,不依赖于bash功能)。

#!/bin/sh

START=
END=

function h2d {
    echo "ibase=16; $@"|bc
}

function d2h {
    echo "obase=16; $@"|bc
}

# convert to decimal
START_DEC=`h2d ${START}`
END_DEC=`h2d ${END}`

# find length of last hex number
LENGTH=`expr ${#END} - 1`

for i in `nawk "BEGIN{ for(i=${START_DEC};i<=${END_DEC};i++) print i}"`
do
    # convert output to hex
    OUTPUT=`d2h ${i}`

    # calculate output length
    OUTPUT_LENGTH=`expr ${#OUTPUT}`

    # calculate required padding
    PAD_LENGTH=`expr ${LENGTH} - ${OUTPUT_LENGTH}`

    # output padding
    for j in `nawk "BEGIN{ for(j=0;j<=${PAD_LENGTH};j++) print j}"`
    do
        echo -n 0
    done

    # output number
    echo -n ${OUTPUT}\;
done

# for the newline
echo

Sample output:

示例输出:

    $ ./hex-range.sh 91 FF
91;92;93;94;95;96;97;98;99;9A;9B;9C;9D;9E;9F;A0;A1;A2;A3;A4;A5;A6;A7;A8;A9;AA;AB;AC;AD;AE;AF;B0;B1;B2;B3;B4;B5;B6;B7;B8;B9;BA;BB;BC;BD;BE;BF;C0;C1;C2;C3;C4;C5;C6;C7;C8;C9;CA;CB;CC;CD;CE;CF;D0;D1;D2;D3;D4;D5;D6;D7;D8;D9;DA;DB;DC;DD;DE;DF;E0;E1;E2;E3;E4;E5;E6;E7;E8;E9;EA;EB;EC;ED;EE;EF;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;FA;FB;FC;FD;FE;FF;

Regarding output to a text file, just use the shell redirection operator:

关于输出到文本文件,只需使用 shell 重定向运算符:

 $./hex-range.sh 91 FF > output.txt

回答by Dave

I'm almost there having picked through some simple commands and cobbled a very simple script together that pads properly and creates exactly the output I need:

我几乎已经完成了一些简单的命令并将一个非常简单的脚本拼凑在一起,该脚本可以正确填充并创建我需要的输出:

#!/bin/sh
#Script to test for loop
i=10 #put start num in here
j=20 #put end num in here
for ((  a=i ;  a <= j;  a++  ))
do
printf '&#x%05x;' "$a" >> output.txt
done

回答by Felipe Kühne

Late reply, but here we go. I was just trying to create a file containing a sequence of bytes ranging from 0 to 255. Here is what I've got:

迟到的回复,但我们走了。我只是想创建一个包含从 0 到 255 的字节序列的文件。这是我得到的:

for n in $(seq 0 255); do printf "\x$(echo "obase=16; $n" | bc)" >> seq.bin; done

It is now exactly what was asked, but one can easily figure out how to change the command to do that.

现在正是被问到的,但是人们可以很容易地弄清楚如何更改命令来做到这一点。

Hope it helps.

希望能帮助到你。

回答by Danek Duvall

Here's another implementation, which doesn't take all the original constraints into account (namely the zero padding and the semicolon separator), but might be useful to someone nevertheless:

这是另一个实现,它没有考虑所有原始约束(即零填充和分号分隔符),但可能对某些人有用:

bc <<< "obase=16; ibase=16; for (i = $low; i <= $high ; i++) i"

It avoids a separate fork by using a here-string (though even the more portable version of piping the string to bcisn't too bad), and then lets bcdo all the computation and conversion. You can remove ibase=16to allow for decimal inputs (and you can set obaseto something else to have octal or binary or whatever).

它通过使用 here-string 避免了单独的分叉(尽管即使是更便携的将字符串管道化的版本bc也不错),然后让我们bc进行所有的计算和转换。您可以删除ibase=16以允许十进制输入(并且您可以设置obase为其他内容以具有八进制或二进制或其他内容)。

Ideally, I think, this would all be built in to seq, though the documentation for the GNU version suggests that they'd rather you do it yourself:

理想情况下,我认为,这将全部内置到 中seq,尽管 GNU 版本的文档表明他们宁愿您自己做:

If you want hexadecimal integer output, you can use printf to perform the conversion:

$ printf '%x\n' $(seq 1048575 1024 1050623)

fffff

1003ff

1007ff

如果需要十六进制整数输出,可以使用 printf 进行转换:

$ printf '%x\n' $(seq 1048575 1024 1050623)

fffff

1003ff

1007ff