Официальная возможность получить лицензионный софт бесплатно.
Giveaway of the Day
Это не реклама!

Щелкните для получения прогноза по Биробиджану


понедельник, 23 августа 2021 г.

Bash: рисование рамок или повтор символа нужное количество раз

 Понадобилось мне рисовать рамочку вокруг выводимого из скрипта сообщения.

Нарисовать ее вокруг заготовленного текста не проблема. Но как быть, если текст меняется и его длина заранее неизвестна, то есть, нельзя заранее нарисовать рамочку нужной длины. Рисовать с запасом - не вариант, душа просит красоты.

Отсюда переходим к другой задаче: как повторить символ или набор символов N-ое число раз, чтобы динамически менять ширину рамочки.

Элегантное решение нашлось в комментариях здесь:

head -c 80 < /dev/zero | tr '\0' '.'

То есть, загружаем нужное количество символов с кодом 0x00 из псевдоустройства /dev/zero, а потом в полученном "тексте" меняем каждый такой символ на нужный нам.

Там же предложено и несколько других вариантов, но на мой взгляд этот лучший. По крайней мере, для моих целей. В скрипте обрабатывается переадресация почты и если переадресация для выбранного пользователя уже настроена, то надо предупредить об этом. Настроенный адрес пересылки находится в переменной SENDING_TO

ALRDY='| !!! УЖЕ ПЕРЕСЫЛАЕТ ПОЧТУ НА '$SENDING_TO' |'
ALRDY_LINE='+'`head -c $(( ${#ALRDY}-2 )) </dev/zero|tr '\0' '-'`'+'
echo $ALRDY_LINE
echo $ALRDY
echo $ALRDY_LINE

В переменную ALRDY помещаем шаблонную строку - фиксированный текст и место для вставки переменной. По краям стоят символы "вертикальная черта", они образуют боковые стороны рамки. А в переменную ALRDY_LINE поместим нужное количество дефисов, размещенных между двумя плюсиками - "углами" рамки. Т.к. верхняя и нижняя стороны рамки одинаковы, то используем только одну переменную, но ничто не мешает использовать их две или больше, в зависимости от.

Веселье начинаем в следующей строке. В начале и в конце добавляем знак "+" к ALRDY_LINE, а между ними результат слегка переработанной команды из примера в начале поста.

${#ALRDY} возвращает длину переменной в СИМВОЛАХ (не в байтах! поэтому юникод работает нормально)

$(( ... )) - это арифметика, из полученной длины переменной ALRDY вычитаем 2, то есть, не принимаем в расчет начальную и конечную вертикальные черточки, поскольку над ними будут не дефисы, а два добавленных вручную плюса.

Результат этого выражения используем как параметр для ключа -c команды head, и вся комбинация обозначает "получить из /dev/zero символы в количестве "длина переменной ALRDY минус два" и заменить каждый из них на дефис". Так как к ALRDY_LINE пририсовываем еще два плюсика, то длины ALRDY и ALRDY_LINE становятся равными.

И вот примерно что получается:

+-----------------------------------------------------+
| !!! УЖЕ ПЕРЕСЫЛАЕТ ПОЧТУ НА bobylova_mv@jcx.srkz.ru |
+-----------------------------------------------------+

+---------------------------------------------+
| !!! УЖЕ ПЕРЕСЫЛАЕТ ПОЧТУ НА kmv@khv.cpsu.su |
+---------------------------------------------+

Просто и очень текстово :-)

В принципе, эту идею можно использовать и для генерации таблиц, а не только рамочек, но у меня в этом необходимости нет.


среда, 4 августа 2021 г.

WMIC и серийный номер APC ИБП

 Обект WMI Win32_Battery имеет много интересных свойств, одно из них - deviceId. Но ИБП от APC пихают в это поле всё подряд - от серийного номера до версий firmware.

Возникла задача: выделить только серийный номер, при этом остальные свойства, которые wmic возвращает в виде непрерывной строки, поля в которой разделяются вертикальной чертой (|) остались на месте.

В конце концов родилось вот такое:

wmicc.sh ИМЯ_КОМПА|tail -n +3 |sed -r "s/([0-9][A-Z][0-9]{4}[A-Z][0-9]{5})[^|]*/\1/g" |datamash transpose -t \| |column -t -s \|

wmicc.sh - это скрипт-обертка, передающий wmic-у вспомогательные параметры - авторизацию и т.п., а так же параметры отбора.

tail обрезает первые 2 строки, в которых содержится ненужный мне мусор.

datamash transpose преобразует последовательные строки в столбцы

column придает этим столбцам красивую ширину

А самое интересное делает sed. В поле deviceId текст выглядит примерно так:

1A2152Z12345  American Power ConversionBack-UPS XS 650CI FW:892.R2.I USB FW:R2

Первое алфавитно-цифровое сочетание и есть серийный номер ИБП, причем 2 цифры сразу после первой буквы (A21) - это год выпуска (пример серийника выше - условный, так что год в нём 2021). Но вот всё остальное до конца строки мне ни к чему.

Поля, как уже сказано, отделяются друг от друга вертикальной чертой, поэтому задача была оставить только серийник, убрав всё остальное до границы поля. Поэтому регэксп читается примерно так:

  1. найти сочетание вида ЦБЦЦЦЦБЦЦЦЦЦ (Ц - цифра, Б - буква), обозначить его как "группа 1"
  2. в той же строке сразу после этой группы искать любое количество любых символов кроме вертикальной черты
  3. заменить найденное в п.п.1 и 2 на то, что находится в "группа 1"
  4. Профит!
$ echo "1A2152Z12345  American Power ConversionBack-UPS XS 650CI FW:892.R2.I USB FW:R2|" |sed -r "s/([0-9][A-Z][0-9]{4}[A-Z][0-9]{5})[^|]*/\1/g"

1A2152Z12345|

Хитрость была в том, что я далеко не сразу понял, как именно указать, что нужно искать всё до ближайшего разделителя полей. Для выполнения таких подстановок ключ -r обязателен, иначе sed ругается.

понедельник, 2 августа 2021 г.

Windows 10 определяет HDD как SSD

Подготовил образ для переустановки системы. Готовил его на компе с SSD.

Заливаю его на комп с HDD и обнаруживаю, что дефрагментация диска невозможна: он, несмотря на правильное определение всех его свойств, рассматривается как SSD, дефрагментация которого не имеет смысла и оптимизатор пишет, что она невозможна.

Решение здесь:(ответ от DavidELindsay()

1. Открываем командную строку от имени администратора (*)

2. Выполняем winsat formal.

3. PROFIT!

(*) поскольку винда после 98-ой пигшется индусскими наркоманами, то даже winsat /? невозможно выполнить из обычной командной строки, даже если войти в систему с администраторской учеткой.