#bash #awk #replace #hexdump #xxd
#bash #awk #заменить #шестнадцатеричный дамп #xxd
Вопрос:
у меня есть 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
мастер 🙂 Спасибо.
Комментарии:
1. Извините, не ясно. Можете ли вы уточнить, что вы пытаетесь сделать?
2. Я пытаюсь изменить одну цифру mac-адреса. Мне нужна эта конкретная позиция, и мне нужно заменить ее другим случайным шестнадцатеричным символом. И мне нужно сделать это с помощью awk, если возможно, вместо использования так, как я уже это сделал. Выполните poc, и вы увидите
3. Изменение mac-адреса в указанной позиции — это нормально, но является ли генерация случайной строки путем вызова
xxd
также обязательным требованием?4. Требуется другой символ… но я пытаюсь избежать использования xxd
Ответ №1:
Что-то подобное может работать с начальным значением из $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)
какому 2-му символу 4-го столбца.
Комментарии:
1. Подождите … это не работает, если вы установили mac как «11:11:11:11:11:11», это не печать mac с измененным только одним символом… он печатает «11:11:11:03:11:11» но это должно быть «11:11:11:13:11:11»
Ответ №2:
Вам не нужен xxd
or hexdump
. urandom
также сгенерирует nubmers, которые соответствуют кодировкам цифр и букв, используемых для представления шестнадцатеричных чисел, поэтому вы можете просто использовать
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, мы выполняем обход, используя оператор modulo %
( 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}"
«Однострочная» версия:
mac=00:00:00:00:00:00
printf %s%X%s\n "${mac::10}" "$(((16#${mac:10:1} 1 RANDOM)))" "${mac:11}"
Комментарии:
1. @OscarAkaElvis забыл об одном требовании. Подождите, пока я отредактирую.
2. Вам нужно добавить проверку того, что новая цифра отличается от исходной
3. Да, иногда он печатает 00:00:00:00:00:00 чего я хочу избежать … в этом случае мне нужна цифра, отличная от исходного «0»
4. srand() не очень случайный. Должно быть лучшее начальное значение, чем время суток. в противном случае несколько вызовов в быстрой последовательности получат один и тот же результат
5. @OscarAkaElvis Исправил проблему.
Ответ №3:
в bash встроен printf и функция random (если вы ей доверяете):
different_mac_digit() {
new=$1
while [[ $new = $1 ]]; do
new=$( printf "%X" $(( RANDOM%16 )) )
done
echo $new
}
Вызвать с символом, который должен быть заменен в качестве аргумента.
Комментарии:
1. Это может быть… но я подожду какого-нибудь решения oneliner, если это возможно. Спасибо, я уже проголосовал за
Ответ №4:
Другой 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
Комментарии:
1. да, еще одно отличное решение с использованием awk. поддержано, спасибо
Ответ №5:
$ mac="00:00:00:00:00:00"
$ awk -v m="$mac" -v p=11 'BEGIN{srand(); printf "%s%X%sn", 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%sn", 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