Добавление строки в файл только в том случае, если оно еще не существует

Мне нужно добавить следующую строку в конец файла конфигурации:

include "/configs/projectname.conf"

в файл с именем lighttpd.conf

Я использую sed для этого, но не могу понять, как это сделать.

Как мне вставить его только в том случае, если строка еще не существует?

Ответ 1

Просто будь проще :)

grep + echo должно быть достаточно:

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
  • -q молчи
  • -x соответствует всей строке
  • Шаблон -F представляет собой простую строку
  • https://linux.die.net/man/1/grep

Редактировать: включены предложения @cerin и @thijs-wouters.

Ответ 2

Это было бы чистым, читаемым и повторно используемым решением, использующим grep и echo для добавления строки в файл, только если он еще не существует:

LINE='include "/configs/projectname.conf"'
FILE='lighttpd.conf'
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"

Ответ 3

Здесь a sed версия:

sed -e '\|include "/configs/projectname.conf"|h; ${x;s/incl//;{g;t};a\' -e 'include "/configs/projectname.conf"' -e '}' file

Если ваша строка находится в переменной:

string='include "/configs/projectname.conf"'
sed -e "\|$string|h; \${x;s|$string||;{g;t};a\\" -e "$string" -e "}" file

Ответ 4

Если вы пишете в защищенный файл, ответы @drAlberT и @rubo77 могут не сработать, так как нельзя судить >>. Таким же простым решением было бы использовать tee --append (или, в MacOS, tee -a):

LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF "$LINE" "$FILE"  || echo "$LINE" | sudo tee --append "$FILE"

Ответ 5

Если однажды кому-то еще придется иметь дело с этим кодом как с "унаследованным кодом", то этот человек будет благодарен, если вы напишите менее экзотерический код, такой как

grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
  echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi

Ответ 6

другое решение sed всегда добавляет его в последнюю строку и удаляет уже существующий.

sed -e '$a\' -e '<your-entry>' -e "/<your-entry-properly-escaped>/d"

"правильно-экранированный" означает поместить регулярное выражение, которое соответствует вашей записи, т.е. избежать всех контрольных элементов регулярного выражения из вашего входа в приложение, т.е. поставить обратную косую черту под символом ^ $/*? +().

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

Ответ 7

использовать awk

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file

Ответ 8

Ответы, использующие grep, неверны. Вам нужно добавить опцию -x, чтобы она соответствовала всей строке, в противном случае строки, такие как #text to add все равно будут совпадать при поиске добавления именно того text to add.

Таким образом, правильное решение выглядит примерно так:

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar

Ответ 9

Используя sed: он будет вставлен в конце строки. Вы также можете передать переменные, как обычно, конечно.

grep -qxF "port=9033" $light.conf
if [ $? -ne 0 ]; then
  sed -i "$ a port=9033" $light.conf
else
    echo "port=9033 already added"
fi

Использование oneliner sed

grep -qxF "port=9033" $lightconf || sed -i "$ a port=9033" $lightconf

Использование echo может не работать под root, но будет работать так. Но это не позволит вам автоматизировать процесс, если вы захотите это сделать, поскольку он может запросить пароль.

У меня была проблема, когда я пытался редактировать из корня для конкретного пользователя. Просто добавление $username раньше было для меня исправлением.

grep -qxF "port=9033" light.conf
if [ $? -ne 0 ]; then
  sudo -u $user_name echo "port=9033" >> light.conf
else
    echo "already there"    
fi

Ответ 10

Мне нужно было отредактировать файл с ограниченными правами на запись, поэтому необходимо sudo. работая от ghostdog74 и используя временный файл:

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file > /tmp/file
sudo mv /tmp/file file