Linux 仅当文件不存在时才向文件追加一行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3557037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 20:23:38  来源:igfitidea点击:

Appending a line to a file only if it does not already exist

linuxsedterminal

提问by Benjamin Dell

I need to add the following line to the end of a config file:

我需要将以下行添加到配置文件的末尾:

include "/configs/projectname.conf"

to a file called lighttpd.conf

到一个名为 lighttpd.conf

I am looking into using sedto do this, but I can't work out how.

我正在考虑使用它sed来执行此操作,但我不知道如何使用。

How would I only insert it if the line doesn't already exist?

如果该行不存在,我将如何插入它?

采纳答案by drAlberT

Just keep it simple :)

保持简单:)

grep+ echoshould suffice:

grep+ echo就足够了:

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

Edit: incorporated @cerin and @thijs-wouters suggestions.

编辑:合并@cerin 和@thijs-wouters 建议

回答by ghostdog74

use awk

使用 awk

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

回答by Paused until further notice.

Here's a sedversion:

这是一个sed版本:

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

If your string is in a variable:

如果您的字符串在变量中:

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

回答by webdevguy

I needed to edit a file with restricted write permissions so needed sudo. working from ghostdog74's answer and using a temp file:

我需要编辑一个写权限受限的文件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

回答by Robin479

another sed solution is to always append it on the last line and delete a pre existing one.

另一种 sed 解决方案是始终将其附加在最后一行并删除一个预先存在的行。

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

"properly-escaped" means to put a regex that matches your entry, i.e. to escape all regex controls from your actual entry, i.e. to put a backslash in front of ^$/*?+().

“正确转义”意味着放置一个与您的条目匹配的正则表达式,即从您的实际条目中转义所有正则表达式控件,即在 ^$/*?+() 前面放置一个反斜杠。

this might fail on the last line of your file or if there's no dangling newline, I'm not sure, but that could be dealt with by some nifty branching...

这可能会在文件的最后一行失败,或者如果没有悬挂的换行符,我不确定,但这可以通过一些漂亮的分支来处理......

回答by rubo77

This would be a clean, readable and reusable solution using grepand echoto add a line to a file only if it doesn't already exist:

这将是一个干净、可读和可重用的解决方案grepecho仅当文件不存在时才使用并在文件中添加一行:

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

If you need to match the whole line use grep -xqF

如果需要匹配整行使用 grep -xqF

Add -sto ignore errors when the file does not exist, creating a new file with just that line.

添加-s以在文件不存在时忽略错误,仅使用该行创建一个新文件。

回答by hamx0r

If writing to a protected file, @drAlberT and @rubo77 's answers might not work for you since one can't sudo >>. A similarly simple solution, then, would be to use tee --append(or, on MacOS, tee -a):

如果写入受保护的文件,@drAlberT 和@rubo77 的答案可能对您不起作用,因为您不能 sudo >>。那么,一个类似的简单解决方案是使用tee --append(或者,在 MacOS 上,tee -a):

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

回答by Marcelo Ventura

If, one day, someone else haveto deal with this code as "legacy code", then that person will be grateful if you write a less exoteric code, such as

如果有一天,其他人不得不把这段代码当作“遗留代码”来处理,那么如果你写了一个不那么显眼的代码,那个人会很感激,比如

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

回答by Thijs Wouters

The answers using grep are wrong. You need to add an -x option to match the entire line otherwise lines like #text to addwill still match when looking to add exactly text to add.

使用 grep 的答案是错误的。您需要添加一个 -x 选项来匹配整行,否则#text to add在查找精确添加text to add.

So the correct solution is something like:

所以正确的解决方案是这样的:

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

回答by Rakib Fiha

Using sed:It will insert at the end of line. You can also pass in variables as usual of course.

使用 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

Using oneliner sed

使用单行 sed

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

Using echomay not work under root, but will work like this. But it will not let you automate things if you are looking to do it since it might ask for password.

在 root 下使用 echo可能不起作用,但会像这样工作。但是,如果您想这样做,它不会让您自动化,因为它可能会要求输入密码。

I had a problem when I was trying to edit from the root for a particular user. Just adding the $usernamebefore was a fix for me.

当我尝试从根目录为特定用户进行编辑时遇到问题。只是添加$usernamebefore 对我来说是一个修复。

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