用其他随机字符替换十六进制字符(可能吗?)

时间:2019-03-02 11:41:16

标签: bash awk replace hexdump xxd

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

from ctypes import windll
user32 = windll.user32
user32.SetProcessDPIAware()

我的脚本的问题是使用#!/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 意味着另一个依赖...我想避免使用它(并非所有Linux默认都包含它)。我使用xxd命令对此有另一种解决方法,但是使用它却处于同一阶段...但是我的脚本已经具有强制性的hexdump依赖性,所以...可以使用{ {1}}?我需要一个awk管理员:)谢谢。

5 个答案:

答案 0 :(得分: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)的第四列的第二个字符。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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

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

当然,您也可以将整个脚本替换为awk脚本。以下GNU awk脚本将用与旧行不同的随机十六进制符号替换每行的第11个符号。使用<<< macaddress,我们可以将macaddress馈送到其stdin,而不必使用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}"

答案 3 :(得分: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

或oneliner:

$ awk -v n=11 -v s=$RANDOM 'BEGIN{FS=OFS=""}{srand(s);while((r=sprintf("%x",rand()*16))==$n);$n=r}1' <<< $mac

答案 4 :(得分: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