Добавление строки в файл только в том случае, если оно еще не существует
Мне нужно добавить следующую строку в конец файла конфигурации:
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
Редактировать:
включены предложения @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