Ещё немного про random() в bc
Как я уже рассказывал, bc под «Линуксом» очень старый, — на всех машинах, куда у меня есть доступ, установлена версия 1.07.1
Ранее я обнаружил недокументированную функцию random(), но генератор случайных чисел в линуксовом bc не инициализируется и функция выдаёт на старте всегда одно и тоже число. Её можно покрутить снаружи случайное число раз и это исправляет ситуацию, но способ, который я тогда придумал для этого, так себе.
Сегодня, пока ехал в такси, придумывал ещё более так себе способы это сделать.
Мысль моя крутилась вокруг запуска через утилиту env. В мире командной строки так частенько делают, так что этот способ как будто бы чуть более честный, так шелл тут не используется:
#!/usr/bin/env -S -i seed_="0${XDG_SESSION_ID};while(seed_--).=random()#" bc /proc/self/environ
print random()
quit()Здорово, правда?
Вся чёрная магия сосредоточена в первой строке. Файл /proc/self/environ формируется в «Линуксе» для каждого запущенного процесса и содержит унаследованные переменные окружения. Так как там много ненужного нам мусора, очищаем его целиком при помощи ключа -i утилиты env.
Далее мы создаём переменную окружения seed_, а внутри её формируем небольшую программу, которая запустится до нашего кода. Для bc результат будет выглядеть так:
seed_=0123456
while(seed_--).=random()
#^@
print random()
quit()Я развернул односрочную программу в многострочную для удобства.
Вместо 123456, конечно, будет подставлено число из переменной окружения $XDG_SESSION_ID, которая содержит число. Ноль там впереди, чтобы не случилось ничего страшного, если эта переменная в вашем дистрибутиве «Линукс» отсутствует.
Мне кажется, это неплохой способ, жаль только что содержимое $XDG_SESSION_ID остаётся одинаковым на всём протяжении жизни сессии. То есть, если запустить программу несколько раз в одном и том же окне терминала, случайные числа будут генерироваться всегда в одной и той же последовательности.
В конце файла /proc/self/environ всегда есть символ с кодом ноль, который мог бы нам всё испортить, но мы спрятали его за символом комментария — #.
Как видно, функция random() вызывается seed_ раз, что позволяет остановиться
Несложно додуматься до похожего способа, который позволяет читать число
Комментарии 18
https://ru.wikipedia.org/?title=/dev/rando … ev/urandom
dd if=/dev/random bs=4 count=1 status=none | od -An -t u4 | bc
кстати, оригинальная идея,в shebang вставить запуск
В <tt>env</tt> можно засунуть только значения переменных, результат выполнения программы туда не поместить. Тут подойдёт способ, который я придумал вчера, но хотелось без запуска шелла обойтись.
Не самый плохой вариант!
$ bc ––version
fish: Unknown command: bc
похоже в баше таки есть таймстамп
$ echo ${EPOCHSECONDS}
1738875578
$ echo ${EPOCHREALTIME}
1738875599.715386
$ env -S -i mtest="${EPOCHSECONDS}"
mtest=1738875693
А
неа :)
1.08.1-1, 2025-01-05
$ dc
fish: Unknown command: dc
Но вообще в арче похоже свежий bc: bc
Ещё в моём wayland этот «рандом» бы тоже работал так себе: XDG_SESSION_ID=1 :)
Это тоже очень старый, на самом деле, на «Маке» — 6.5.0. Такое ощущение, что <tt>bc</tt> на две ветки развалился — линуксовый, который не развивается, и… ну… фришный, который на «Маке»; там видно развитие.
Хах:-) А <tt>cat /proc/self/sessionid</tt> что выдаёт?
Похоже что в линуксе gnu bс (https://ftp.gnu.org/gnu/bc/), а у вас там bsd bc (https://git.gavinhoward.com/gavin/bc)
Тоже один, это похоже существует только для того чтобыX-овые приложения запускались в wayland и иницилизируется какой-нибудь прослойкой.
$ cat /proc/self/sessionid
1
У меня есть вот эти две, но я бы не надеялся на них (возможно что без моего терминала их не будет):
WINDOWID=108603892187776
ALACRITTY_WINDOW_ID=108603892187776
Но когда я залогинился в текстовую консоль, то стало XDG_SESSION_ID=3! Надо просто перед запуском залогиниться пару тысяч раз!
Да у меня скорее размышления и эксперименты, а не готовые решения, я всё же не учебник по bc пишу:-)