Как сделать так, чтобы остальная часть строки осталась неизменной?

Вопрос или проблема

У меня есть строка

* {@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

Объяснение кода:

  1. Шаблон: '/^\* {@jira: PIVOT/' — этот шаблон указывает, что мы будем работать только с линиями, которые начинаются с * {@jira: PIVOT. Это поможет нам фильтровать строки и избежать ненужных замен в других строках.

  2. Замены:

    • sub(/{/,"\\{"): первый вызов sub() заменяет первую открытую фигурную скобку на экранированную версию \{.
    • sub(/}/,"\\}"): второй вызов sub() заменяет первую закрытую фигурную скобку на экранированную версию \}.
  3. Вывод: 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-подобных системах.

Оцените материал
Добавить комментарий

Капча загружается...