При анализе производительности или поиске ошибок в работе систем на платформе 1С:Предприятие основным инструментом исследования становится Технологический журнал (ТЖ). Однако файлы логов ТЖ могут достигать гигантских размеров, и ручной поиск в них невозможен. Системные администраторы и разработчики часто прибегают к инструментам командной строки Linux (Bash) для быстрой фильтрации данных. Для предварительной нормализации логов перед анализом подойдёт утилита для перезаписи технологического журнала в удобный для Linux формат.
Типичная задача — извлечь конкретный фрагмент строки, например, имя файла и точное время события, которые находятся между определенными разделителями. Рассмотрим, как решить проблему извлечения данных, когда стандартные подходы с sed не срабатывают из-за особенностей структуры лога 1С.
Типичная строка события ТЖ (например, для события ADMIN) выглядит следующим образом:
rphost_13556/24070415.log:08:52.586002-0,ADMIN,4,process=rphost--999
Предположим, нам нужно получить данные, находящиеся между первым символом слеша / и первым дефисом -. Обычное регулярное выражение типа .+ захватывает максимально возможную последовательность символов. Проанализируем ситуацию: в строке ТЖ после нужного нам фрагмента могут идти другие дефисы (например, в параметре process=rphost--999). Из-за этого sed при использовании точки «проглатывает» всю строку до самого последнего дефиса. Это называется «жадным» поведением (greedy matching).
Одним из самых надежных и понятных способов является использование утилиты awk. Разберем по шагам, как работает предложенная конструкция:
echo "rphost_13556/24070415.log:08:52.586002-0,ADMIN,4,process=rphost--999" | awk -F'/' '{split($2, a, "-"); print a[1]}'
Проанализируем работу этой команды:
-F'/' указывает awk использовать слеш в качестве разделителя полей. После этого строка делится на две части: $1 ("rphost_13556") и $2 ("24070415.log:08:52.586002-0...").split($2, a, "-") берет вторую часть строки и разбивает её в массив a, используя дефис в качестве разделителя.print a[1] выводит первый элемент этого массива, который и является искомым значением (имя лога и время).Если нам принципиально использовать sed, мы должны заставить его остановиться на первом встреченном дефисе. Поскольку стандартный sed не поддерживает «ленивые» квантификаторы (такие как .*?), мы применим технику исключающих символьных классов.
Рассмотрим выражение:
echo "rphost_13556/24070415.log:08:52.586002-0,ADMIN,4,process=rphost--999" | sed 's|.*/\([^-]*\)-.*|\1|'
Выясним причину, по которой это работает:
. мы используем конструкцию [^-]*, которая означает «любое количество символов, кроме дефиса».\1 мы выводим только ту часть, которая попала в круглые скобки.В современных дистрибутивах Linux утилита grep поддерживает расширенные регулярные выражения Perl (флаг -P). Это позволяет использовать «ленивые» квантификаторы напрямую, что делает код более читаемым.
Посмотрим на пример:
echo "rphost_13556/24070415.log:08:52.586002-0,ADMIN,4,process=rphost--999" | grep -oP '(?<=/).*?(?=-)'
Разберем, что здесь происходит:
(?<=/) — это «просмотр назад» (lookbehind). Мы ищем место, перед которым стоит слеш, но сам слеш в результат не включаем..*? — это ленивый квантификатор. Он ищет минимально возможное количество символов.(?=-) — это «просмотр вперед» (lookahead). Мы ищем место, после которого стоит дефис, не включая сам дефис в выдачу.-o заставляет grep вывести только совпавшую часть строки.Для тех, кто заботится о максимальной производительности скриптов обработки ТЖ, наиболее эффективным будет использование встроенных механизмов Bash. Это позволяет избежать вызова внешних процессов (таких как sed или awk) для каждой строки лога, что существенно ускоряет обработку больших файлов.
Рассмотрим пошагово выполнение операций над переменной:
string="rphost_13556/24070415.log:08:52.586002-0,ADMIN,4,process=rphost--999"
# Удаляем всё до первого слеша включительно
tmp=${string#*/}
# Удаляем всё после первого дефиса включительно
result=${tmp%%-*}
echo $result
Этот метод работает молниеносно, так как все манипуляции происходят внутри памяти текущего процесса оболочки.
Если формат строки ТЖ строго фиксирован, проще всего применить двойную «нарезку» с помощью cut. Это наиболее простой для понимания метод.
Разберем логику:
echo "rphost_13556/24070415.log:08:52.586002-0,ADMIN,4,process=rphost--999" | cut -d'/' -f2 | cut -d'-' -f1
cut -d'/' -f2 берет вторую колонку, разделенную слешем.cut -d'-' -f1 берет первую колонку из результата, разделенную дефисом.При написании регулярных выражений для 1С важно учитывать специфику данных. Дефис в строке 08:52.586002-0 является разделителем между временем события и его длительностью в микросекундах. Сразу после этого дефиса всегда идет цифра.
Если вы опасаетесь, что дефисы могут встретиться внутри пути к файлу или в имени самого лога, можно уточнить шаблон поиска. Например, искать «до дефиса, за которым следует цифра». В grep -P это будет выглядеть так: (?<=/)[^/]+(?=-\d). Это повысит надежность ваших скриптов при анализе сложных логов распределенных систем.
Резюме: выбор инструмента зависит от ваших целей. Для разовой проверки в консоли удобнее cut или awk. Для сложных шаблонов используйте grep -P. Если же вы пишете высокопроизводительный парсер для обработки гигабайтов логов, используйте встроенные средства Bash ${string#*/}. Для комплексной автоматизации сбора и парсинга потоков логов можно использовать решение на базе Vector для технологического журнала.