Игнорировать комментарии (#) с помощью sed, но держать строки нетронутыми

У меня есть файл конфигурации, в котором я хочу в основном редактировать строки без комментирования, но не прокомментированные строки. Я использую sed.

Например, у меня есть файл с именем file.txt:

test
# test
# test
test

Я хочу заменить "test" на "TEST", но НЕ касайтесь прокомментированных строк. Конечный результат должен показывать:

test
# test
# test
test

Ответ 1

sed '/^#/!s/test/TEST/g' /path/to/infile

Выход

$ sed '/^#/!s/test/TEST/g' infile
TEST
# test
# test
TEST

* Примечание. Если ваше единственное требование для комментария состоит в том, что самый первый символ без пробелов - это #, то вы можете использовать:

sed '/^[[:space:]]*#/!s/test/TEST/g' /path/to/infile

Выход

$ sed '/^[[:space:]]*#/!s/test/TEST/g' infile
TEST
# test
 # test
TEST

Ответ 2

Я не эксперт sed, но regexp для соответствия этим строкам будет выглядеть примерно так:

^[^#].*test

  • ^ - начало строки
  • [^#] - первый символ, ничего, кроме #
  • .* - несколько символов, undefined
  • test - строка, которую вы ищете

Ответ 3

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

sed -r 'h;s/[^#]*//1;x;s/#.*//;(substitution command);G;s/(.*)\n/\1/' file.txt

В вашем случае это будет:

sed -r 'h;s/[^#]*//1;x;s/#.*//;s/test/TEST/g;G;s/(.*)\n/\1/' file.txt

Преимущество этого решения над другими решениями заключается в том, что он также будет работать, если есть комментарий, начинающийся позже в строке, как показано в примере ниже. Поскольку это решение использует буфер хранения sed, это решение невозможно, если вам нужно использовать буфер удержания для чего-то еще.

Ввод

test
# test
test # test
test

Выход

test
# test
test # test
test

Объяснение

  • h; - Сохранить буфер хранения
  • s/[^#]*//1; - удалить все до #
  • x; - Обмен с буфером удержания
  • s/#.*//; - Удалить комментарий
  • s/test/TEST/g; - Заменить все вхождения test на test
  • G; - Добавить буфер + hold + hold (комментарий)
  • s/(.*)\n/\1/ - удалить последнюю строку новой строки

Для использования \1 необходим переключатель -r.

Ответ 4

AWK:

awk '!/^[[:space:]]*#/ {gsub(/test/,"TEST")} 1' file.txt

Ответ 5

если у вас есть Ruby (1.9 +)

ruby -ne 'print $_ !~ /^\s*#/ ?gsub("test","TEST"):$_' file