Читать в телеге. Когда-то там были посты не только от меня.
Случайная выборка из csv
Безо всяких питонов сделать случайную выборку данных из текстового файла можно командой shuf
:
cat dataset.csv | shuf | head -n100 | tee random_sample.csv
Закрытие старых ревью в Upsource
К сожалению, теорию разбитых окон можно наблюдать и в разработке. Поэтому периодически стоит наводить чистоту в коде, трекерах задач (можно называть это модной фразой “груминг бэклога”) и прочих штуках.
Недавно дошли руки до того, чтобы почистить незакрытые ревью в Upsource. Поскольку в проекте их было более 400 штук, а из коробки такой фичи нет, то в мою коллекцию добавился еще один скрипт для автоматизации всякой дичи.
Внезапно, у Upsource есть API, но есть нюанс: названия методов придется угадывать самостоятельно по названию DTO. В остальном все относительно просто: берем список ревью по подобранному методом тыка запросу, и закрываем по одному. Все вместе можно посмотреть в gist.
Форматирование строки в python
Я тот еще консерватор и не очень люблю новое. Поэтому статьи про
"hello, {}!".format("world")
"hello, {0} and {0} again!".format("world")
"hello, {name}".format(name="world")
вызывали у меня легкое раздражение: я не видел никаких существенных преимуществ перед старым добрым "hello %s" % "world"
. Но пора бы очнуться от летаргического сна, и посмотреть на Python 3.6+ (выпущенный в 2016).
Там есть f"hello, {name}!"
, у которого в скобках будет полноценное выражение, т.е. можно сделать f"hello, {''.join(map(chr, [87, 111, 114, 108, 100]))}!"
. Этот вариант хорош для большинства случаев, особенно с учетом того, что почти во всех распространенных языках строковая интерполяция плюс-минус так и работает. Кроме Java, но она всегда была немного “особенной”.
Пример случая, когда такая интерполяция не очень уместна: фиксированный формат, который используется несколько раз и вынесен в “константу”. Например, у меня в скриптах довольно часто встречается такое:
XX_PATH = "http://%s/some/api/path/%s"
...
response = requests.get(XX_PATH % (host, param), ...)
Тут придется садиться на один из стульев: %
или format
.
Поиск удаленного в истории git
Искать в текущей версии любой дурак может, а как найти что-то, что было удалено в истории git?
git --no-pager grep -i "search term" $(git rev-list --all)
--no-pager
уже может быть знаком по journalctl, -i
, как и в обычном grep
, говорит об неважности регистра, а вызов $(git rev-list --all)
дает список всех ревизий.
Будет вывод в формате хэш коммита:/путь/к/файлу: совпавшая строка
. А дальше переключаемся на нужную ревизию и ищем как раньше.
Что означает поле update в результатах update by query в Elasticsearch?
Смотрим в документацию:
updated
The number of documents that were successfully updated.
Внимание, вопрос: учитываются все затронутные документы или все измененные? Вроде как все затронутые, да и обновления могут быть без изменений документа (для того, чтобы обновить документ в индексе, например). Но хочется побольше уверенности.
Роемся в исходниках, недолгий поиск по ключевому слову updated
приводит сначала к WorkerBulkByScrollTaskState, а потом к AbstractAsyncBulkByScrollAction:
switch (item.getOpType()) {
case CREATE:
case INDEX:
if (item.getResponse().getResult() == DocWriteResponse.Result.CREATED) {
worker.countCreated();
} else {
worker.countUpdated();
}
break;
case UPDATE:
worker.countUpdated();
break;
case DELETE:
worker.countDeleted();
break;
}
Тут видно, что в подсчете вообще не учитывается, был ли изменен документ — интересен только тип операции. Соответственно в поле updated
ответа будет число всех затронутых документов, даже если они не менялись. Отличаться от total
оно будет только тогда, когда создаются или удаляются документы. Т.е. total = updated + deleted + created
.
Люблю Open Source продукты за то, что можно при желании разобраться почти в любой проблеме.
Из чего только не строят графы
Прикольная статья про то, как чувак строил графы по автодоплнению поисковой выдачи гугла ключевое слово vs
. Перевод для нихтферштейнов.
Кто-то сделал даже страничку, чтобы поиграться самому. Запрос к гуглу идет напрямую из браузера, так что персонализация поиска скорее всего будет работать (BB is watching you).
Кто может залогинится на сервере по ssh?
Иногда при установке разных сервисов добавляются пользователи в систему. В некоторых случаях — с возможностью логина в систему со стандартным паролем (sic!). Чтобы найти таких редисок, можно выполнить
cat /etc/shadow | grep -v \*\: | grep -v \!\:
И еще потенциально пользователи отсюда могут залогиниться
ls -l /home
Для того, чтобы ограничить доступ, надо в конфиге sshd добавить строчку
AllowUsers user1 user2
Backreference в регулярках
Иногда нужно найти текст, где что-то должно повторяться. Например, найти и заменить повторяющийся паттерн в коде на вызов функции:
someFun(ololo)
anotherFun(ololo)
yetAnotherFun(rrr, ololo)
Если тупо использовать 4 группы, то такой кусочек тоже попадет в результаты:
someFun(alala)
anotherFun(ololo)
yetAnotherFun(qqq, qyqyqy)
А это мы вряд ли хотим. Чтобы указать, что подстроки именно одинаковые, нужно использовать backreference:
someFun\((.*)\)\s*anotherFun\(\1\)\s*yetAnotherFun\([^,]*,\s*\1\)
P.S. Да, я правлю код регулярками и считаю это приемлемым, когда код в таком состоянии, что только так и имеет смысл делать.
Сканер портов
Испытываю теплые чувства к утилите nmap
. С ее помощью можно быстро проверить, какие популярные порты открыты на ip-адресе:
nmap 1.1.1.1
или виден ли какой-нибудь сервис наружу
nmap 192.168.1.123 -p9050
или посканить локальную (или не очень) сетку на предмет доступных хостов
nmap -sn 192.168.1.0/24
или еще чего-нибудь насканить в сети.
Навигация по коду
У IntelliJ есть интересная опция для навигации по коду, кроме известных приемов типа Split View, перехода к определению через Ctrl+B или Ctrl+клик.
Можно делать нумерованные закладки в коде. Для создания закладки — Ctrl+Shift+цифра, для перехода Ctrl+цифра. Закладка ставится на строку и может пригодиться, когда надо быть сразу в двух-трех местах.