如果文件中不存在该行,则将一行内容追加到文件中。

253

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

include "/configs/projectname.conf"

将内容保存到名为lighttpd.conf的文件中。

我正在研究如何使用sed来做到这一点,但是我无法弄清楚如何操作。

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


如果您想要编辑一个ini文件,工具crudini可能是一个不错的选择(但还不能用于lighthttpd)。 - rubo77
25个回答

4

这里有一个 awk 实现:

/^option *=/ { 
  print "option=value"; # print this instead of the original line
  done=1;               # set a flag, that the line was found
  next                  # all done for this line
}
{print}                 # all other lines -> print them
END {                   # end of file
  if(done != 1)         # haven't found /option=/ -> add it at the end of output
    print "option=value"
}

使用以下方式运行:

awk -f update.awk < /etc/fdm_monitor.conf > /etc/fdm_monitor.conf.tmp && \
   mv /etc/fdm_monitor.conf.tmp /etc/fdm_monitor.conf

或者
awk -f update.awk < /etc/fdm_monitor.conf | sponge /etc/fdm_monitor.conf

编辑: 简述:

awk '/^option *=/ {print "option=value";d=1;next}{print}END{if(d!=1)print "option=value"}' /etc/fdm_monitor.conf | sponge /etc/fdm_monitor.conf

我需要一行代码,因为我将其作为系统调用从C程序中发送。 - Evilmachine

3

使用awk

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

是 'file file' 还是只是 'file'? - webdevguy
它被称为“file file”,因为它对同一文件进行了两次遍历。NR==FNR在第一次遍历时为真,但在第二次遍历时不为真。这是一个常见的Awk习语。 - tripleee

3
 sed -i 's/^option.*/option=value/g' /etc/fdm_monitor.conf
 grep -q "option=value" /etc/fdm_monitor.conf || echo "option=value" >> /etc/fdm_monitor.conf

2
几乎所有的答案都有效,但根据我的经验,并不适用于所有的场景或操作系统。唯一在旧系统和新的不同版本的操作系统上起作用的是以下方法。
如果不存在,我需要将KUBECONFIG路径附加到bashrc文件中。所以,我做的是:

我假设它已经存在并将其删除。
使用sed我添加了我想要的字符串。

sed -i '/KUBECONFIG=/d' ~/.bashrc

echo 'export KUBECONFIG=/etc/rancher/rke2/rke2.yaml' >> ~/.bashrc

1
最简单有效的命令,感谢。 - Yassine Chilali

2

这里有一个awk单行命令:

 awk -v s="option=value" '/^option/{f=1;$0=s}7;END{if(!f)print s}' file

这不会对文件进行原地更改,但你可以:

awk '...' file > tmpfile && mv tmpfile file

2

使用 sed,你可以这样说:

sed -e '/option=/{s/.*/option=value/;:a;n;:ba;q}' -e 'aoption=value' filename

如果参数已经存在,它将被替换,否则将添加到文件底部。


如果您想原地编辑文件,请使用-i选项:

sed -i -e '/option=/{s/.*/option=value/;:a;n;:ba;q}' -e 'aoption=value' filename

8
这似乎根本不起作用。它会在每一行后面添加“option=value”。不确定它是如何得到两个赞的。你可以使用“$aoption=value”,但我似乎无法将其与前一个匹配相条件化,因此它只会附加到末尾。 - sosiouxme

2
sed -i '1 h
1 !H
$ {
   x
   s/^option.*/option=value/g
   t
   s/$/\
option=value/
   }' /etc/fdm_monitor.conf

将所有文件加载到缓冲区中,在结尾处更改所有出现的内容,如果没有更改发生,则添加到结尾


1

仅使用sed,我建议采用以下解决方案:

sed -i \
    -e 's#^include "/configs/projectname.conf"#include "/configs/projectname.conf"#' \
    -e t \
    -e '$ainclude "/configs/projectname.conf"' lighttpd.conf

s 将行 include "/configs/projectname.conf 用自身替换(在此使用#作为分隔符)

t 如果替换成功,则跳过其余命令

$a 否则跳转到最后一行并在其后追加 include "/configs/projectname.conf


如果您正在使用GNU sed(而不是“-e t”),请将文本从英语翻译成中文。仅返回翻译后的文本。 - undefined

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

使用一行命令的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

欢迎来到stackoverflow!在发布答案之前,请仔细阅读问题 - OP问如何使用sed插入。 - Markoorn

1

尝试:

LINE='include "/configs/projectname.conf"'
sed -n "\|$LINE|q;\$a $LINE" lighttpd.conf >> lighttpd.conf

使用管道作为分隔符,如果找到$LINE则退出。否则,在末尾追加$LINE

由于我们只在sed命令中读取文件,我认为通常情况下不会有覆盖问题(这取决于您的shell设置)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接