All streams
Search
Write a publication
Pull to refresh
40
0
Павлов Николай Александрович @ZyXI

Инженер

Send message
Если что, то их можно также именовать:
(zyx-desktop:zyx:~) 3 % echo 'abbabaa' | perl -p -i -e 's/(?<fst>a(?&snd)*)(?<snd>b(?&fst)*)/1($1)2($2)/'
1(abba)2(baa)
и нумеровать относительно текущей скобки:
(zyx-desktop:zyx:~) 3 % echo 'abbabaa' | perl -p -i -e 's/(a(?+1)*)(b(?-2)*)/1($1)2($2)/'
1(abba)2(baa)
. -2 потому, что считаются открывающие скобки, соответствующие захватывающим группам, в заданном направлении.
Есть:
(zyx-desktop:zyx:~) 3 % echo 'abbabaa' | perl -p -i -e 's/(a(?2)*)(b(?1)*)/1($1)2($2)/' 
1(abba)2(baa)
PCRE тоже поддерживает, но из‐за отсутствия pcresed я не могу показать, какой кусок текста сопоставляется какой скобке.
Рекурсия есть, но не везде. Я знаю только о perl и PCRE. Учтите, что рекурсия в регулярных выражениях невозможна по определению (если не ошибаюсь, то использование ссылок ((a*)\1 для нахождения вхождения чётного количества a в строке), также невозможно). Только регулярные выражения в большинстве движков уже давно не регулярные.
В perl и PCRE можно использовать рекурсивные регулярные выражения: простейший пример: echo '((((()))))' | grep --color=always --perl-regexp '\((?R)?\)' подсветит вам все скобки (при условии, что grep собран с поддержкой PCRE). Можно ссылаться как на всё регулярное выражение (как в моём примере), так и на конкретную именованную или нумерованную группу.

В perl также можно вставлять в регулярное выражение куски кода, которые будут выполнены во время сравнения регулярного выражения со строкой ((?{code}) и (??{code})), но использование этой возможности не является хорошей идеей (в perldoc perlre в первом абзаце описания даже стоит предупреждение).
Если пользователь взял и поменял конфиг в /etc, то он не только пользователь, но и администратор. Я не вижу ничего плохого в том, чтобы администраторы использовали vimdiff для проверки корректности слияния или для самого слияния.

Кроме того, если вы не хотите писать слияние по сложным правилам, специфичным для каждого пакета (и при этом справляться с проблемами вроде «что делать, если пользователь пропустил пару‐тройку [десятков] релизов?»), то единственная вещь с алгоритмом, работающим для всех текстовых файлов, которая мне приходит в голову — это VCS.
Её же можно заставить использовать для слияния конфигов ваш скрипт, если нужно, при этом не рискуя испортить файл настроек навсегда (что возможно, если не делалось резервное копирования, а в вашем алгоритме слияния ошибка).
Потеря с VCS?! Кроме того, weirded спрашивал, есть ли что‐то для слияние настроек, подобное тому, что он видел. Я указал альтернативу, которой сам пользуюсь. Очень частые изменения настроек: исправление ошибки в комментариях, единственный (он же по‐умолчанию) стал не единственным и был вынесен в настройку: с этим VCS отлично справляется. С бо́льшими изменениями есть больши́е шансы нарваться на конфликт при слиянии, но в этом случае вы будете видеть, какая часть файла была написана человеком, а какая — пришла из RPM.

Кроме того, если настраиваемый компонент важен, то вы должны проводить тестирование. Возможность review после слияния тоже никто не отменял. Да и если вам не хочется полагаться на VCS, вы можете заставить VCS всегда сливать с помощью vimdiff. При этом вы опять же будете видеть, какие настройки пришли откуда.
Хранить настройки в Mercurial, из RPM — помещать в одну ветку, свои изменения — все в другую, после обновления делать слияние?

В крайнем случае дописать к этому свой mergetool: при наличии общего предка слияние не должно быть слишком хитрым.
Расскажите, как вы, используя слоты, получите debug и нормальную сборку python-2.7.5 на одной машине?
LILO и GRUB оба вроде бы умеют грузить ядро с RAID. Только у меня не получилось в своё время заставить работать: LILO грузит только с первого диска в зеркале, тогда как на момент первичной настройки его не было (использовался degraded массив, потому что первый диск уже был занят системой, которую и требовалось перенести на RAID). В чём была проблема с GRUB я не помню.

Думаю, вопрос именно об этом: может ли GRUB загрузить ядро с RAID (предполагая, что /boot находится на зеркале, а не в отдельном разделе)?
Я начал использовать initramfs аккурат после того, как мне захотелось иметь RAID1 на /. Правда, мне непонятно, зачем в initramfs udev: mdadm умеет находить массивы и без него. Кроме того, можно указать ему явно, какие диски во что требуется собирать в /etc/mdadm.conf (genkernel копирует его в initramfs, если указана настройка MDADM_CONFIG).

Если что, использование genkernel для создания initramfs не означает, что вам нужно использовать genkernel для сборки ядра.
А в каком направлении шли итерации? Первый вариант кажется каким‐то шаблонным. Последний очень приятен на вид (за исключением небольшого числа комбинаций вида «светлое на светлом»). Но обычно направление «слева направо» соответствует «от старого к новому»; а в этом случае мне непонятно, зачем вы жалуетесь: стало лучше, чем было.
А почему в качестве примера «уютного места» стоит зачастую очищающийся дистрибутивом при перезагрузки и/или вообще находящийся исключительно в оперативной памяти /tmp (причём, кажется, в моей Gentoo используется и то, и то)?
Кстати, а у RCS есть ветки и слияние?
Git поднять просто, даже очень (если только вам не нужен сервер, доступный по ssh, хотя это тоже не высшая математика). Обучиться работе с ним — сложнее, но многие уже и так умеют. Поэтому он и предпочтительнее: с ним зачастую человек уже работал сам, либо имеет под рукой кого‐то, кто работал, а кто сейчас работает с RCS?

Я под такие задачи всегда выбираю mercurial, но в большинстве случаев это просто персональные предпочтения, а не следствие наличия у mercurial какой‐либо отсутствующей у git возможности.
Судя по TODO, он не решает даже проблемы слияния (в TODO написано, что хорошо бы иметь ветку с неизменёнными конфигами; а как вы будете сливать ваш вариант и обновлённый, если таковой ветки нет?). Секретные файлы тоже есть в TODO.

Кстати, а как в Debian и Ubuntu поступают с пользовательскими изменениями? Судя по Debian Policy Manual¹, он спрашивает пользователя, если файл был изменён как пользователем, так и maintainer’ом пакета (что лучше portage, который будет спрашивать всегда, если файл изменён пользователем), и etckeeper ничего с этим не делает. Но во многих случаях достаточно автоматического слияния, производимого системой контроля версий, а в остальных вы получаете привычный 3-way merge, а не (в Gentoo!) «вот два файла, твой старый и новый, теперь вспомни, что ты там наменял, а что оставил как есть» (с etckeeper вспомнить должно быть проще).

¹
If neither the user nor the package maintainer has changed the file, it is left alone. If one or the other has changed their version, then the changed version is preferred — i.e., if the user edits their file, but the package maintainer doesn't ship a different version, the user's changes will stay, silently, but if the maintainer ships a new version and the user hasn't edited it the new version will be installed (with an informative message). If both have changed their version the user is prompted about the problem and must resolve the differences themselves.
Собственно, я даже не вижу никакого смысла в использовании git без ветки неизменённых конфигов. Основное преимущество /etc под контролем VCS для меня — это автоматическое слияние, ещё удобна возможность отката. Резервное копирование всё равно необходимо делать отдельно; тем более, что это git (он позволяет переписывать историю, что совершенно недопустимо, если ваша цель — инкрементальное резервное копирование), что вы исключаете из‐под контроля множество существенных файлов (вроде того же /etc/shadow) и что, судя по описанию, репозиторий находится пока только в / (т.е. не предохраняет от повреждения ФС /).
Я тоже не вмешиваюсь в работу portage. Portage не хранит нетронутые файлы, только их контрольные суммы. Соответственно, нет никакой понятной etc-update «ветки нетронутых конфигов» — etc-update работает только с настройками пользователя в /etc и положенными туда ._cfg* файлами. Отсюда никакого автоматического слияния (нет общего предка в виде нетронутого файла). Соответственно, etc-update предлагает слить /etc/conf.d/consolefont каждый раз, когда обновляется openrc и то же самое для других файлов. Поэтому etc-update мною никогда не используется.

Если бы я сделал что‐то с portage, то он бы писал прямо в ветку с нетронутыми файлами. А так я беру и переношу все изменения из /etc в /var/etc-default, делаю commit там, делаю pull в /etc, делаю merge. Требует отсутствия локальных изменений (можно обойти требование, создав третий клон, сделав pull+merge там и pull+update в /etc). Если что, это Mercurial. Git может требовать, а может и не требовать отсутствия локальных изменений — я не помню.
С чем вы будете путать $a++? Здесь нет потенциальной проблемы.

Кроме того, не нужно быть говнокодером, чтобы при чтении цепочки однотипных условий не заметить отличие находящихся между ними операторов. Если вы поставите переносы строк перед/после каждого оператора ИЛИ, то код резко станет более читаемым и без скобок. Но появятся слишком короткие строки и слишком длинное условие. Скобки лучше. Исходный же вариант прямо‐таки создан для запутывания.
Если у вас Gentoo, то определённо есть «обновления» для конфигурационных файлов, складывающиеся в {path}/._cfg{number}_{fname}. Как вы их обрабатываете?

У меня есть отдельная ветка с файлами только по‐умолчанию и ветка с моими изменениями к ним. Всё, что делает portage (._cfg* (правильно переименованное), новые файлы, автоматически изменённые файлы), идёт в первую ветку без каких‐либо изменений. А потом делается слияние.

Относительно корня и /var/lib/portage/world: у меня он перемещён в /etc/portage. Символические ссылки и/или mount -o bind (точнее, соответствующая запись в fstab) позволяют такое проделать со всеми нужными файлами. Не могу сказать, лучше это или хуже вашего варианта, но добавление файлов в вашем варианте определённо проще.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity