用不同的随机字符替换十六进制字符(awk 可能吗?)
Replace hex char by a different random one (awk possible?)
有一个 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
我的脚本的问题是使用 xxd
意味着另一个依赖项...我想避免它(并非所有 Linux 默认都包含它)。我有另一个使用 hexdump
命令的解决方法,但使用它我处于同一阶段......但我的脚本已经具有强制性 awk
依赖性,所以......可以使用 awk
?我需要一位 awk
大师 :) 谢谢。
bash 有内置的 printf 和一个随机函数(如果你相信它的话):
different_mac_digit() {
new=
while [[ $new = ]]; do
new=$( printf "%X" $(( RANDOM%16 )) )
done
echo $new
}
以要替换的字符作为参数调用。
您不需要 xxd
或 hexdump
。 urandom
还将生成与用于表示十六进制数的数字和字母的编码相匹配的数字,因此您可以只使用
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
提供给它的标准输入,而不必使用 echo
或类似的东西。
awk 'BEGIN { srand(); pos=11 } {
old=strtonum("0x" substr([=11=],pos,1))
new=(old + 1 + int(rand()*15)) % 16
print substr([=11=],1,pos-1) sprintf("%X",new) substr([=11=],pos+1)
}' <<< 00:00:00:00:00:00
这里的技巧是在要修改的数字上添加一个介于 1 和 15(包括两者)之间的随机数。如果我们最终得到一个大于 15 的数字,我们使用模运算符 %
环绕(16
变为 0
,17
变为 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}"
"One-liner"版本:
mac=00:00:00:00:00:00
printf %s%X%s\n "${mac::10}" "$(((16#${mac:10:1}+1+RANDOM%15)%16))" "${mac:11}"
这样的事情可能适用于 $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(, 2, 1))
= substr(, 1, 1) s
} 1' <<< "$mac"
00:00:00:03:00:00
在 while 循环中,我们继续直到十六进制数字不等于 substr(, 2, 1)
第 4 列的第 2 个字符。
另一个 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
$ 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
有一个 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
我的脚本的问题是使用 xxd
意味着另一个依赖项...我想避免它(并非所有 Linux 默认都包含它)。我有另一个使用 hexdump
命令的解决方法,但使用它我处于同一阶段......但我的脚本已经具有强制性 awk
依赖性,所以......可以使用 awk
?我需要一位 awk
大师 :) 谢谢。
bash 有内置的 printf 和一个随机函数(如果你相信它的话):
different_mac_digit() {
new=
while [[ $new = ]]; do
new=$( printf "%X" $(( RANDOM%16 )) )
done
echo $new
}
以要替换的字符作为参数调用。
您不需要 xxd
或 hexdump
。 urandom
还将生成与用于表示十六进制数的数字和字母的编码相匹配的数字,因此您可以只使用
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
提供给它的标准输入,而不必使用 echo
或类似的东西。
awk 'BEGIN { srand(); pos=11 } {
old=strtonum("0x" substr([=11=],pos,1))
new=(old + 1 + int(rand()*15)) % 16
print substr([=11=],1,pos-1) sprintf("%X",new) substr([=11=],pos+1)
}' <<< 00:00:00:00:00:00
这里的技巧是在要修改的数字上添加一个介于 1 和 15(包括两者)之间的随机数。如果我们最终得到一个大于 15 的数字,我们使用模运算符 %
环绕(16
变为 0
,17
变为 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}"
"One-liner"版本:
mac=00:00:00:00:00:00
printf %s%X%s\n "${mac::10}" "$(((16#${mac:10:1}+1+RANDOM%15)%16))" "${mac:11}"
这样的事情可能适用于 $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(, 2, 1))
= substr(, 1, 1) s
} 1' <<< "$mac"
00:00:00:03:00:00
在 while 循环中,我们继续直到十六进制数字不等于 substr(, 2, 1)
第 4 列的第 2 个字符。
另一个 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
$ 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