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
Appending a line to a file only if it does not already exist
提问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 sed
to 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
-q
be quiet-x
match the whole line-F
pattern is a plain string- https://linux.die.net/man/1/grep
-q
安静-x
匹配整行-F
模式是一个普通的字符串- https://linux.die.net/man/1/grep
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 sed
version:
这是一个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 grep
and echo
to add a line to a file only if it doesn't already exist:
这将是一个干净、可读和可重用的解决方案grep
,echo
仅当文件不存在时才使用并在文件中添加一行:
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 -s
to 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 add
will 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 $username
before was a fix for me.
当我尝试从根目录为特定用户进行编辑时遇到问题。只是添加$username
before 对我来说是一个修复。
grep -qxF "port=9033" light.conf
if [ $? -ne 0 ]; then
sudo -u $user_name echo "port=9033" >> light.conf
else
echo "already there"
fi