Bash-скрипт для раскомментирования строк с ведущими пробелами в файле с определенным шаблоном

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

Я пытаюсь раскомментировать конкретные строки из файла с шаблонами в Oracle Linux 8.6, используя Bash. В некоторых строках есть ведущие пробелы, где комментарии не удаляются. Я пытался раскомментировать закомментированные строки с помощью sed и grep для совпадения с шаблонами.

sed -n '/\<19\>/,+1p' cmfile|grep '38'|sed -i '/38/s/^#//g' cmfile

Содержимое файла:

    #pd19_ORA svg38
#pd19_ORA sil38
#pd29_ORA sil37

Первая строка все еще закомментирована после использования sed с inplace, но комментарий второй строки удален.

Вывод:

    #pd19_ORA svg38
pd19_ORA sil38
#pd29_ORA sil37

Как удалить комментарий у первой строки, которая имеет ведущие пробелы, не удаляя ведущий пробел?

Ожидаемый вывод:

    pd19_ORA svg38
pd19_ORA sil38
#pd29_ORA sil37

Вы можете попробовать awk, и следующая команда может сделать это. Если вам нужно, чтобы конкретные строки 19 и 38 находились на определенных местах, вы должны указать это в вопросе:

awk '/19/ && /38/ {sub(/#/,"")}1' 

Эта команда ищет строку с 19 и 38 и удаляет символ #. Затем выводит строку (независимо от того, совпадает она и редактирована или нет)

awk '/19/ && /38/ {sub(/#/,"")}1' input_file
    pd19_ORA svg38
pd19_ORA sil38
#pd29_ORA sil37

Если вы хотите убедиться, что # является первым символом, который не является пробелом в строке, вы можете модифицировать скрипт следующим образом:

 awk '/19/ && /38/ && $1 ~ "^#" {sub(/#/,"")}1' input_file

Предположим, вы хотите раскомментировать строки, которые содержат 38, и которые следуют за строкой, содержащей словоограниченное¹ 19, как предполагает ваша попытка:

perl -pi -e 's/^\s*\K#// if $flag && /38/; $flag = /\b19\b/' your-file

В вашем:

sed -n '/\<19\>/,+1p' cmfile|grep '38'|sed -i '/38/s/^#//g' cmfile

Команда sed -i '/38/s/^#//g' cmfile не читает свой ввод, она только редактирует cmfile на месте, удаляя ведущий # на любой строке, содержащей 38 (кстати, g избыточно, так как может быть только одна подстановка).

Таким образом, sed -n '/\<19\>/,+1p' cmfile|grep '38' бессмысленен, так как ничего не читает его вывод.

Также обратите внимание, что все -i, +1, \<\> являются нестандартными расширениями GNU², в то время как команда perl будет работать на любой системе³.


¹ В любом случае, 19 в pd19_ORA не является словоограниченным, так как и d, и _ являются словесными символами; если вы хотите сопоставить 19, который не является ни предшествующим, ни следующим десятичным числом, используйте (?<!\d)19(?!\d) вместо \b19\b (эквивалент perl для ex\<19\>).

² Строго говоря, \<\> возникло в ex/vi, а не GNU sed, и -i было скопировано GNU sed из perl, а ,+1 из ed.

³ Хотя вам потребуется perl версии 5.10.0 (с 2007 года) или новее для \K (чтобы Keep сохранить то, что слева от него). На системах с более старой версией perl вы можете заменить s/^\s*\K#// на s/^(\s*)#/$1/.

^# соответствует только # в начале строки. Одной из альтернатив для разрешения пробелов перед комментарием является ^[ \t]*#

Итак, эта строка должна работать:

sed -n '/\<19\>/,+1p' cmfile|grep '38'|sed -i '/38/s/^[ \t]*#//g' cmfile

Я думаю, вы хотите удалить лидирующий символ # из всех строк, содержащих число 19, сохраняя любые ведущие пробелы

sed -E '/[^0-9]19([^0-9]|$)/s/^([[:space:]]*)#/\1/' cmfile

Это ищет строки, содержащие 19 (но без цифр по обе стороны, таких как 019 или 193), так как я не мог заставить \<19\> соответствовать любой из ваших строк здесь.

В случае, если вы хотите, чтобы строки содержали 19 и 38, вам просто нужно расширить исходное соответствие строки:

sed -E '/[^0-9]19([^0-9]|$)(.*[^0-9]|)38([^0-9]|$)/s/^([[:space:]]*)#/\1/' cmfile

В обоих случаях для всех таких совпадающих строк мы захватываем любые ведущие пробелы, предшествующие символу #, чтобы мы могли добавить их обратно в вывод

Ответ или решение

Для решения проблемы удаления символа # из строк, содержащих определенные шаблоны, на Oracle Linux 8.6 с использованием Bash, нужно учесть наличие ведущих пробелов в строках. Ваш текущий подход с использованием sed имеет некоторые ограничения, поскольку он не обрабатывает ведущие пробелы правильно из-за специфики поиска по началу строки. Рассмотрим несколько альтернативных методов решения этой задачи.

Решение с использованием awk

awk является мощным инструментом для обработки текстовых данных в Unix-подобных системах. Пользуйтесь awk, чтобы упростить задачу по удалению # в нужных строках, сохранив при этом ведущие пробелы:

awk '/19/ && /38/ {sub(/^[ \t]*#/, "")}1' cmfile

Объяснение

  1. Поиск строк: Команда ищет строки, которые содержат как 19, так и 38.
  2. Удаление комментария: Функция sub заменяет комментарий # в начале строки, сохраняя при этом любые ведущие пробелы.
  3. Вывод результата: 1 в конце команды указывает на то, что каждая строка, независимо от того, была ли она изменена, должна быть выведена.

Решение с использованием perl

perl также широко используется для сложных текстовых трансформаций и поддерживает регексы, которые могут быть недостаточно мощными в sed:

perl -pi -e 's/^\s*#// if /19/ && /38/' cmfile

Объяснение

  1. Условие поиска: Команда ищет совпадение строк, содержающих 19 и 38.
  2. Удаление комментария: Используется конструкция s/^\s*#//, которая удаляет символ # при его нахождении в начале строки, игнорируя ведущие пробелы.

Решение с использованием расширенного sed

Если вы все-таки предпочитаете sed, нужно адаптировать команду, чтобы она учитывала ведущие пробелы:

sed -i -E '/19/ && /38/ s/^[ \t]*#//' cmfile

Объяснение

  1. Поиск строк: Используется расширенный формат регулярных выражений от sed с опцией -E.
  2. Удаление комментария: Шаблон ^[ \t]*# позволяет корректно обрабатывать строки с лидирующими пробелами перед #.

Заключение

Каждый из этих методов имеет свои преимущества. Выберите подходящий, исходя из ваших предпочтений и установленных инструментов. Эти команды исправят текущие проблемы в вашем скрипте и позволят легко удалять символы комментария из строк с нужным шаблоном, сохраняя их форматирование. Убедитесь, что вы используете инструменты, которые соответствуют совместимости вашей системы, чтобы избежать нежелательных результатов или ошибок.

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

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