Добавление строки в файл, только если он еще не существует - PullRequest
123 голосов
/ 24 августа 2010

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

include "/configs/projectname.conf"

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

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

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

Ответы [ 10 ]

223 голосов
/ 24 августа 2010

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

grep + echo должно хватить:

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

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

65 голосов
/ 19 января 2015

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

LINE='include "/configs/projectname.conf"'
FILE='lighttpd.conf'
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
12 голосов
/ 24 августа 2010

Вот версия 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
7 голосов
/ 02 мая 2018

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

grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
  echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi
7 голосов
/ 31 марта 2017

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

LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF "$LINE" "$FILE"  || echo "$LINE" | sudo tee --append "$FILE"
5 голосов
/ 08 мая 2014

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

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

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

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

3 голосов
/ 24 августа 2010

используйте awk

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file
1 голос
/ 27 февраля 2019

Используя 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
1 голос
/ 30 декабря 2018

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

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

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
0 голосов
/ 29 апреля 2014

Мне нужно было отредактировать файл с ограниченными правами на запись, поэтому необходимо 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...