如何使用 bash 生成有效的随机 mac 地址。
地址的前半部分应该始终保持不变,如下所示
00-60-2F-xx-xx-xx
只是 x 值应该是随机生成的?
答案1
过去我曾使用过以下方法完成此操作:
echo 00-60-2F-$[RANDOM%10]$[RANDOM%10]-$[RANDOM%10]$[RANDOM%10]-$[RANDOM%10]$[RANDOM%10]
但这样只能使它们处于 0-9 范围内。就我的目的而言,这已经足够好了。
可能更好的解决方案是使用 printf:
printf '00-60-2F-%02X-%02X-%02X\n' $[RANDOM%256] $[RANDOM%256] $[RANDOM%256]
工作原理如下:
- printf 程序基于 C“printf”函数,该函数以“格式字符串”作为第一个参数,然后以附加参数填充格式字符串。
- 格式字符串中的 % 引入了一个“格式说明符”,它可以是一个或多个字符,用于指示如何格式化参数。
- 格式说明符中的前导零 (0) 表示应在生成的数字输出中用前导零填充至指定的宽度。
- 2 表示说明符应占用两个字符的宽度进行显示。
- X 结束说明符,表示应将其解释为数字并以十六进制显示。由于它是大写的,因此字母 af 也应大写。
- \n 是换行符——printf 将反斜杠解释为转义码,可用于显示其他字符,通常是换行符等棘手的字符。
- 格式说明符中的其余字符将按原样打印出来,其中包括开头的“00-06-2F-”和格式说明符之间的破折号。
- 其余参数是 shell 变量替换(用 $ 表示),并包含一个数学表达式,该表达式是一个模 256 的随机数(RANDOM)。这会产生一个介于 0 和 255 之间的随机数。
答案2
这里有一条鱼。
这个 shell 脚本会生成你寻求的随机字符串:
#!/bin/bash
hexchars="0123456789ABCDEF"
end=$( for i in {1..6} ; do echo -n ${hexchars:$(( $RANDOM % 16 )):1} ; done | sed -e 's/\(..\)/-\1/g' )
echo 00-60-2F$end
我确实在这里展示了如何从命令行运行它,但是在看了 Dennis Williamson 复杂但被赞成的)解决方案后,我发现人们期望的答案是他们不需要自己做任何工作的答案。
答案3
- 生成适当大小的整数,如下所示:http://tldp.org/LDP/abs/html/randomvar.html
- 像这样转换为十六进制:http://snipplr.com/view/2428/convert-from-int-to-hex/
- 在三个随机生成的块之间添加破折号
#!/bin/bash
RANGE=255
#set integer ceiling
number=$RANDOM
numbera=$RANDOM
numberb=$RANDOM
#generate random numbers
let "number %= $RANGE"
let "numbera %= $RANGE"
let "numberb %= $RANGE"
#ensure they are less than ceiling
octets='00-60-2F'
#set mac stem
octeta=`echo "obase=16;$number" | bc`
octetb=`echo "obase=16;$numbera" | bc`
octetc=`echo "obase=16;$numberb" | bc`
#use a command line tool to change int to hex(bc is pretty standard)
#they're not really octets. just sections.
macadd="${octets}-${octeta}-${octetb}-${octetc}"
#concatenate values and add dashes
echo $macadd
#echo result to screen
#note: does not generate a leading zero on single character sections. easily remediedm but that's an exercise for you
或者用python:
from random import randint
def gen_mac_char():
return hex((randint(0,16))).split('x')[1]
def gen_mac_pair():
return ''.join([gen_mac_char(), gen_mac_char()])
def gen_last_half_mac(stem):
return '-'.join([stem, gen_mac_pair(), gen_mac_pair(), gen_mac_pair()])
print(gen_last_half_mac('00-60-2F'))
请注意,python 版本仅使用 16 宽的字段来生成十六进制字符,因此您不必担心零填充 - 方法已修改以解决注释。
答案4
#!/bin/bash
LC_CTYPE=C
MAC=00-60-2F
for i in {1..3}
do
IFS= read -d '' -r -n 1 char < /dev/urandom
MAC+=$(printf -- '-%02x\n' "'$char")
done
printf '%s\n' "$MAC"
其工作方式的关键在于:
LC_CTYPE=C
- 允许字符 > 0x7FIFS=
\t
- 禁用(tab)、\n
(换行) 和空格的解释-d ''
- 允许换行-r
允许\
(并且应该几乎总是习惯性地与 一起使用read
)格式说明符
-%02x\n
使输出为文字连字符,后跟两位十六进制数(如果合适,包括前导零)。此处的换行符是多余的,可以省略。获取范围为 0 到 255(到)内的
read
单个字节(-n 1
)。/dev/urandom
00
FF
循环中最后一个参数中的单引号
printf
使字符输出为其数值(“A”输出为“65”)。请参阅POSIX 规范printf
其中写道:如果前导字符是单引号或双引号,则该值应为单引号或双引号后字符的底层代码集中的数值。