Подтвердить что ты не робот

Как добавить строку в sed, если совпадение не найдено

Я использую следующую команду sed для замены некоторых параметров в файле конфигурации:

sed -i 's/^option.*/option=value/g' /etc/fdm_monitor.conf

Теперь у меня есть одна проблема. Если строка не существует, я хочу добавить ее в нижнюю часть файла.

Я вызываю это с помощью popen из программы на C. Я попытался использовать awk.

4b9b3361

Ответ 1

Попробуйте следующее:

grep -q '^option' file && sed -i 's/^option.*/option=value/' file || echo 'option=value' >> file

Ответ 2

Используя sed, вы можете сказать:

sed -e '/option=/{s/.*/option=value/;:a;n;:ba;q}' -e 'aoption=value' filename

Это заменит параметр, если он существует, иначе он добавит его в нижнюю часть файла.


Используйте параметр -i, если вы хотите отредактировать файл на месте:

sed -i -e '/option=/{s/.*/option=value/;:a;n;:ba;q}' -e 'aoption=value' filename

Ответ 3

Как однострочный awk-единственный:

awk -v s=option=value '/^option=/{$0=s;f=1} {a[++n]=$0} END{if(!f)a[++n]=s;for(i=1;i<=n;i++)print a[i]>ARGV[1]}' file

ARGV [1] - ваш вход file. Он открывается и записывается в цикл for блока END. Открытие file для вывода в блоке END заменяет необходимость в утилитах типа sponge или записи во временный файл, а затем mv временного файла на file.

Два назначения массива a[] накапливают все выходные строки в a. if(!f)a[++n]=s добавляет новый option=value, если основной цикл awk не смог найти option в file.

Я добавил некоторые пробелы (не многие) для удобочитаемости, но вам действительно нужно всего одно место во всей awk-программе, пробел после print. Если file включает # comments, они будут сохранены.

Ответ 4

здесь находится однострочный awk:

 awk -v s="option=value" '/^option/{f=1;$0=s}7;END{if(!f)print s}' file

это не делает изменения на месте в файле, но вы можете:

awk '...' file > tmpfile && mv tmpfile file

Ответ 5

 sed -i 's/^option.*/option=value/g' /etc/fdm_monitor.conf
 grep -q "option=value" /etc/fdm_monitor.conf || echo "option=value" >> /etc/fdm_monitor.conf

Ответ 6

Здесь реализация awk

/^option *=/ { 
  print "option=value"; # print this instead of the original line
  done=1;               # set a flag, that the line was found
  next                  # all done for this line
}
{print}                 # all other lines -> print them
END {                   # end of file
  if(done != 1)         # haven't found /option=/ -> add it at the end of output
    print "option=value"
}

Запустите его, используя

awk -f update.awk < /etc/fdm_monitor.conf > /etc/fdm_monitor.conf.tmp && \
   mv /etc/fdm_monitor.conf.tmp /etc/fdm_monitor.conf

или

awk -f update.awk < /etc/fdm_monitor.conf | sponge /etc/fdm_monitor.conf

EDIT: Как однострочный:

awk '/^option *=/ {print "option=value";d=1;next}{print}END{if(d!=1)print "option=value"}' /etc/fdm_monitor.conf | sponge /etc/fdm_monitor.conf

Ответ 7

sed -i '1 h
1 !H
$ {
   x
   s/^option.*/option=value/g
   t
   s/$/\
option=value/
   }' /etc/fdm_monitor.conf

Загрузите весь файл в буфер, в конце, измените все вхождения и, если никаких изменений не произошло, добавьте в конец

Ответ 8

Я разработал решение kev grep/sed, установив переменные, чтобы уменьшить дублирование.

Задайте переменные в первой строке (подсказка: $_option должна соответствовать всем в строке вверх до значения [включая любой разделитель типа = или:]).

_file="/etc/ssmtp/ssmtp.conf" _option="mailhub=" _value="my.domain.tld" \
        sh -c '\
            grep -q "^$_option" "$_file" \
            && sed -i "s/^$_option.*/$_option$_value/" "$_file" \
            || echo "$_option$_value" >> "$_file"\
        '

Помните, что sh -c '...' просто влияет на расширение области переменных без необходимости в export. (См. Настройка переменной среды перед тем, как команда в bash не работает для второй команды в канале)

Ответ 9

Вот однострочное седло, которое делает работу inline. Обратите внимание, что он сохраняет местоположение переменной и ее отступ в файле, когда он существует. Это часто важно для контекста, например, когда есть комментарии вокруг или когда переменная находится в отступом. Любое решение, основанное на парадигме "delete-then-append", плохо справляется с этим.

   sed -i '/^[ \t]*option=/{h;s/=.*/=value/};${x;/^$/{s//option=value/;H};x}' test.conf

С общей парой переменных/значений вы можете записать это следующим образом:

   var=c
   val='12 34' # it handles spaces nicely btw
   sed -i '/^[ \t]*'"$var"'=/{h;s/=.*/='"$val"'/};${x;/^$/{s//c='"$val"'/;H};x}' test.conf

Наконец, если вы хотите также сохранить встроенные комментарии, вы можете сделать это с помощью группы catch. Например. если test.conf содержит следующее:

a=123
# Here is "c":
  c=999 # with its own comment and indent
b=234
d=567

Затем запустите этот

var='c'
val='"yay"'
sed -i '/^[ \t]*'"$var"'=/{h;s/=[^#]*\(.*\)/='"$val"'\1/;s/'"$val"'#/'"$val"' #/};${x;/^$/{s//'"$var"'='"$val"'/;H};x}' test.conf

Производит, что:

a=123
# Here is "c":
  c="yay" # with its own comment and indent
b=234
d=567