Вопрос или проблема
У меня есть строка
* {@jira: PIVOT-9968} Предоставить способ передать `IMemoryCollector` в `IInternalMemoryMonitored#getMemoryStatistics(memoryCollector)`, чтобы предотвратить подсчет дублирующихся блоков.
Я хотел экранировать только первый, содержащий номер тикета(?).
написать скрипт для добавления обратного слэша
для моей предыдущей проблемы
* /{@jira: PIVOT-9968/} Предоставить способ передать `IMemoryCollector` в `IInternalMemoryMonitored#getMemoryStatistics(memoryCollector)`, чтобы предотвратить подсчет дублирующихся блоков.
Я пробовал
mawk '/^\* {@jira: PIVOT/ { gsub(/[{} ]/,"\\\\&") } 1' changelog.md > tmp && mv tmp changelog.md
и получил
*\ \{@jira:\ PIVOT-8019\}\ Пивот:\ Добавлены\ функции\ агрегации\ `MaxAppendOnlyFunction`\ и\ \ `MinAppendOnlyFunction`\ которые\ не\ поддерживают\ разбиение\ но\ могут\ быть\ использованы\ в\ агрегатном\ провайдере.
что мне нужно изменить? gsub?
В awk
sub()
заменит первое вхождение совпаденияgsub()
заменит все вхождения совпадения/[{} ]/
говорит о том, что нужно найти любой из 3-х символов:{
,}
и
Если мы уберем пробел (останется /{}/
):
$ awk '/^\* {@jira: PIVOT/ { gsub(/[{}]/,"\\\\&") } 1' changelog.md
* \{@jira: PIVOT-9968\} Предоставить способ передать `IMemoryCollector` в `IInternalMemoryMonitored#getMemoryStatistics(memoryCollector)`, чтобы предотвратить подсчет дублирующихся блоков.
Предполагая, что OP хочет использовать обратный слэш в качестве символа экранирования, и на строке будет только одна пара фигурных скобок, этого должно быть достаточно для удовлетворения требований OP.
Если в одной строке может быть несколько пар фигурных скобок…
$ cat changelog_2.md
* {@jira: PIVOT-1234} новая строка {с несколькими} наборами фигурных скобок {для демонстрации} целей
Запуск нового кода против этого файла неверно изменит все пары фигурных скобок:
$ awk '/^\* {@jira: PIVOT/ { gsub(/[{}]/,"\\\\&") } 1' changelog_2.md
* \{@jira: PIVOT-1234\} новая строка \{с несколькими\} наборами фигурных скобок \{для демонстрации\} целей
Чтобы ограничить замены только первой парой фигурных скобок, мы можем использовать пару вызовов sub()
, где каждый вызов заменяет первое вхождение одного символа; обратите внимание, что мы заменяем /[{}]/
на /{/
и /}/
, и поскольку мы знаем, символ, с которым мы будем сравнивать, мы можем заменить \\&
на фактический символ (для небольшого упрощения кода):
$ awk '/^\* {@jira: PIVOT/ { sub(/{/,"\\{"); sub(/}/,"\\}") } 1' changelog_2.md
* \{@jira: PIVOT-1234\} новая строка {с несколькими} наборами фигурных скобок {для демонстрации} целей
Реализация этого замещения по одному с помощью sed
:
$ sed 's/}/\\}/1; s/{/\\{/1' changelog.md changelog_2.md
* \{@jira: PIVOT-9968\} Предоставить способ передать `IMemoryCollector` в `IInternalMemoryMonitored#getMemoryStatistics(memoryCollector)`, чтобы предотвратить подсчет дублирующихся блоков.
* \{@jira: PIVOT-1234\} новая строка {с несколькими} наборами фигурных скобок {для демонстрации} целей
Где:
- оканчивающий
/1
говорит о том, что нужно заменить первое вхождение - как и в случае с подходом
awk / sub()
, нам нужно выполнить два отдельных замещения, чтобы соответствовать первой паре фигурных скобок
Ответ или решение
Для решения задачи, поставленной в вашем вопросе, мы воспользуемся командой awk
, которая позволяет манипулировать текстом с помощью шаблонов. В данном контексте нам необходимо экранировать только первый экземпляр фигурных скобок {}
в строке, содержащей номер тикета. Помните, что gsub()
заменяет все вхождения, в то время как sub()
заменяет только первое. Это будет полезно, когда необходимо ограничить замену только первой парой фигурных скобок.
Решение
Чтобы экранировать только первые фигурные скобки в строке, мы можем использовать два вызова функции sub()
. Вот как это сделать:
awk '/^\* {@jira: PIVOT/ { sub(/{/,"\\{"); sub(/}/,"\\}") } 1' changelog.md > tmp && mv tmp changelog.md
Объяснение кода:
-
Шаблон:
'/^\* {@jira: PIVOT/'
— этот шаблон указывает, что мы будем работать только с линиями, которые начинаются с* {@jira: PIVOT
. Это поможет нам фильтровать строки и избежать ненужных замен в других строках. -
Замены:
sub(/{/,"\\{")
: первый вызовsub()
заменяет первую открытую фигурную скобку на экранированную версию\{
.sub(/}/,"\\}")
: второй вызовsub()
заменяет первую закрытую фигурную скобку на экранированную версию\}
.
-
Вывод:
1
в конце используется для того, чтобыawk
выводил всю строку, независимо от изменений.
Пример работы
Для файла changelog.md
, содержащего следующие строки:
* {@jira: PIVOT-9968} Provide a way to pass an `IMemoryCollector` to `IInternalMemoryMonitored#getMemoryStatistics(memoryCollector)` in order to prevent the count of duplicated blocks.
После выполнения кода, результат будет следующим:
* \{@jira: PIVOT-9968\} Provide a way to pass an `IMemoryCollector` to `IInternalMemoryMonitored#getMemoryStatistics(memoryCollector)` in order to prevent the count of duplicated blocks.
Обработка нескольких пар скобок
Если в строке могут быть несколько пар фигурных скобок, и вам нужно экранировать только первую пару, вышеуказанный подход остается актуальным. Однако если будут дополнительные условия, следует позаботиться о более сложных логических структурах.
Альтернативное решение с использованием sed
Если по каким-то причинам вы предпочитаете использовать sed
, вот аналогичная команда:
sed 's/{/\\{/; s/}/\\}/' changelog.md > tmp && mv tmp changelog.md
В этом примере:
s/{/\\{/
заменяет первую найденную открытую фигурную скобку.s/}/\\}/
заменяет первую найденную закрытую фигурную скобку.
Заключение
Используемый подход в awk
и sed
позволяет эффективно экранировать только те фигурные скобки, которые нам нужны, не затрагивая остальные части строки. Это решение высокопрофессионально и применимо на практике для обработки текстовой информации в Unix-подобных системах.