1

有一个mac地址,我只需要用一个不同的随机字符(它必须与原始字符不同)替换一个十六进制字符(一个在非常特定的位置)。我使用 xxd 以这种方式完成了它,它可以工作:

#!/bin/bash
mac="00:00:00:00:00:00" #This is a PoC mac address obviously :)
different_mac_digit=$(xxd -p -u -l 100 < /dev/urandom  | sed "s/${mac:10:1}//g" | head -c 1)
changed_mac=${mac::10}${different_mac_digit}${mac:11:6}
echo "${changed_mac}" #This echo stuff like 00:00:00:0F:00:00

我的脚本的问题是 usingxxd意味着另一个依赖项......我想避免它(并非所有 Linux 默认都包含它)。我对此使用hexdump命令有另一种解决方法,但使用它我处于同一阶段...但是我的脚本已经具有强制awk依赖项,所以...可以使用来完成awk吗?我awk在这里需要一个主人:) 谢谢。

4

5 回答 5

2

像这样的东西可能适用于种子值$RANDOM

mac="00:00:00:00:00:00"
awk -v seed=$RANDOM 'BEGIN{ FS=OFS=":"; srand(seed) } {
   s="0"
   while ((s = sprintf("%x", rand() * 16)) == substr($4, 2, 1))
   $4 = substr($4, 1, 1) s
} 1' <<< "$mac"

00:00:00:03:00:00

在 while 循环中,我们继续直到十六进制数字不等于substr($4, 2, 1)第 4 列的第二个字符。

于 2019-03-02T12:28:37.603 回答
1

另一个awk:

$ awk -v n=11 -v s=$RANDOM '                # set n to char # you want to replace
BEGIN { FS=OFS="" }{                        # each char is a field
    srand(s)                                
    while((r=sprintf("%x",rand()*16))==$n);  
    $n=r
}1' <<< $mac

输出:

00:00:00:07:00:00

或单线:

$ awk -v n=11 -v s=$RANDOM 'BEGIN{FS=OFS=""}{srand(s);while((r=sprintf("%x",rand()*16))==$n);$n=r}1' <<< $mac
于 2019-03-02T14:07:50.417 回答
1
$ mac="00:00:00:00:00:00"
$ awk -v m="$mac" -v p=11 'BEGIN{srand(); printf "%s%X%s\n", substr(m,1,p-1), int(rand()*15-1), substr(m,p+1)}'
00:00:00:01:00:00
$ awk -v m="$mac" -v p=11 'BEGIN{srand(); printf "%s%X%s\n", substr(m,1,p-1), int(rand()*15-1), substr(m,p+1)}'
00:00:00:0D:00:00

并确保您获得与开始时不同的数字:

$ awk -v mac="$mac" -v pos=11 'BEGIN {
    srand()
    new = old = toupper(substr(mac,pos,1))
    while (new==old) {
        new = sprintf("%X", int(rand()*15-1))
    }
    print substr(mac,1,pos-1) new substr(mac,pos+1)
}'
00:00:00:0D:00:00
于 2019-03-02T16:01:04.313 回答
1

bash 有 printf 内置函数和一个随机函数(如果你相信的话):

different_mac_digit() {
    new=$1
    while [[ $new = $1 ]]; do
        new=$( printf "%X" $(( RANDOM%16 )) )
    done
    echo $new
}

使用要替换的字符作为参数调用。

于 2019-03-02T12:05:15.317 回答
1

你不需要xxdhexdumpurandom还将生成与用于表示十六进制数字的数字和字母的编码相匹配的数字,因此您可以使用

old="${mac:10:1}"
different_mac_digit=$(tr -dc 0-9A-F < /dev/urandom | tr -d "$old" | head -c1)

当然,您也可以用脚本替换整个脚本awk。以下 GNUawk脚本将用与旧符号不同的随机十六进制符号替换每行的第 11 个符号。有了<<< macaddress我们就可以macaddress在不使用echo或类似的东西的情况下提供给它的标准输入。

awk 'BEGIN { srand(); pos=11 } {
  old=strtonum("0x" substr($0,pos,1))
  new=(old + 1 + int(rand()*15)) % 16
  print substr($0,1,pos-1) sprintf("%X",new) substr($0,pos+1)
}' <<< 00:00:00:00:00:00

这里的技巧是在要修改的数字上添加一个介于 1 和 15(包括两者)之间的随机数。如果我们最终得到一个大于 15 的数字,我们使用模运算符%16变得017变得1等等)环绕。这样可以保证生成的数字与旧数字不同。

但是,如果完全用 bash 编写,同样的方法会更短。

mac="00:00:00:00:00:00"
old="${mac:10:1}"
(( new=(16#"$old" + 1 + RANDOM % 15) % 16 ))
printf %s%X%s\\n "${mac::10}" "$new" "${mac:11}"

“单线”版本:

mac=00:00:00:00:00:00
printf %s%X%s\\n "${mac::10}" "$(((16#${mac:10:1}+1+RANDOM%15)%16))" "${mac:11}"
于 2019-03-02T12:05:35.053 回答