Тема: sed, perl та інша регекс-езотерика
Вирішив створити тему, в якій можна поділитися різними крутими штуками, зробленими на самих регексах (чи майже на самих). У першу чергу, програми, написані на sed, perl та інших подібних мовах. Хоча після успіху perl у 90-х практично в кожній сучасній мові з'явились інструменти для роботи з регулярними виразами — тому чітких обмежень нема, це може бути й php, Python, JS — за умови, що регулярні вирази є основним інструментом реалізації думки автора.
Наприклад, ось такий код:
#!/usr/bin/env sed -f
# Ханойська вежа
# Ввід: кількість дисків цифрами.
# Вивід: розв'язок задачі для заданої кількості дисків.
# Підтримуються числа в діапазоні від 1 до 999,
# за умови достатньої кількості пам'яті та часу :)
s/[^0-9]//g
s/^/000/
s/.*\(.\)\(.\)\(.\)/\1C\2X\3I/
s/0[A-Z]//g
s/\(.\)\(.\)/\1987654321\2/g
s/\([0-9]\)[0-9]*\1//g
:roman
s/[0-9]\([A-Z]\)/\1\1/g
/[0-9]/broman
s/C/XXXXXXXXXX/g
s/X/IIIIIIIIII/g
s/./-/g
s/^..*$/A&B/
:loop
s/\([ABC]\)-\(--*\)\([ABC]\)/\1\2\1\3 \1-\3 \1\3\2\3/g
s/AB\|BA/C/g
s/AC\|CA/B/g
s/BC\|CB/A/g
/--/bloop
s/-/->/g
Або інша реалізація
#!/usr/bin/env sed -f
# Ханойська вежа (з використанням перекодування y/.../.../)
# Приймає числа 1...40
/^0$/bend
s/^/(A->B)/
# Конвертувати 10...40 в a...z,E,F,G,H :
/)1./y/0123456789/abcdefghij/
/)2./y/0123456789/klmnopqrst/
/)3./y/0123456789/uvwxyzEFGH/
s/).\(.\)$/)\1/
:loop
/1$/bend
h
y/AC/CA/
x
y/BC/CB/
G
s/)[^(]*(/ A->B /
y/123456789abcdefghijklmnopqrstuvwxyzEFGH/0123456789abcdefghijklmnopqrstuvwxyzEFG/
bloop
:end
s/[^-> ABC]//g
У другому варіанті вежі основним інструментом є не власне регекси, а простіший інструмент — перекодування. Завдяки цьому, програма працює трохи швидше, ніж попередня.
Обидва скрипти можуть приймати більші числа, ніж реально здатні обробити: оскільки увесь результат у процесі обробки тримається в оперативці, розв'язок задачі для 30 дисків вимагатиме декілька ГБ...