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

include "/configs/projectname.conf"

到一个名为lighttpd.conf的文件

我正在研究使用sed来做到这一点,但我不知道如何。

我怎么能只插入它,如果行已经不存在?


当前回答

 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

其他回答

作为awk专用的一行代码:

awk -v s=option=value '/^option=/{$0=s;f=1} {a[++n]=$0} END{if(!f)a[++n]=s;for(i=1;i<=n;i++)print a[i]>ARGV[1]}' file

ARGV[1]是你的输入文件。它被打开并写入end块的for循环中。在END块中打开文件进行输出,取代了像海绵或写入临时文件,然后将临时文件移动到文件等实用程序的需要。

对数组a[]的两次赋值将所有输出行累加到a中。if(!f)a[++n]=s如果主awk循环在文件中找不到option,则追加新的option=value。

为了可读性,我添加了一些空格(不是很多),但在整个awk程序中只需要一个空格,即打印后的空格。 如果文件包含#注释,它们将被保留。

保持简单就好:)

Grep + echo就足够了:

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

-q安静点 -x匹配整行 -F pattern是一个普通字符串 https://linux.die.net/man/1/grep

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

下面是一个单行sed,它内联完成这项工作。注意,当变量存在时,它会保留变量的位置及其在文件中的缩进。这对于上下文来说通常很重要,比如当周围有注释时,或者当变量位于缩进块中时。任何基于“先删除再追加”范式的解决方案在这方面都失败得很厉害。

   sed -i '/^[ \t]*option=/{h;s/=.*/=value/};${x;/^$/{s//option=value/;H};x}' test.conf

对于一个通用的变量/值对,你可以这样写:

   var=c
   val='12 34' # it handles spaces nicely btw
   sed -i '/^[ \t]*'"$var"'=/{h;s/=.*/='"$val"'/};${x;/^$/{s//c='"$val"'/;H};x}' test.conf

最后,如果还想保留内联注释,可以使用catch组。例如,如果test.conf包含以下内容:

a=123
# Here is "c":
  c=999 # with its own comment and indent
b=234
d=567

然后运行这个

var='c'
val='"yay"'
sed -i '/^[ \t]*'"$var"'=/{h;s/=[^#]*\(.*\)/='"$val"'\1/;s/'"$val"'#/'"$val"' #/};${x;/^$/{s//'"$var"'='"$val"'/;H};x}' test.conf

生产:

a=123
# Here is "c":
  c="yay" # with its own comment and indent
b=234
d=567

使用awk

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

为了减少重复,我通过设置变量详细阐述了kev的grep/sed解决方案。

设置第一行中的变量(提示:$_option将匹配一行中的所有内容,直到值[包括任何分隔符,如=或:])。

_file="/etc/ssmtp/ssmtp.conf" _option="mailhub=" _value="my.domain.tld" \
        sh -c '\
            grep -q "^$_option" "$_file" \
            && sed -i "s/^$_option.*/$_option$_value/" "$_file" \
            || echo "$_option$_value" >> "$_file"\
        '

注意那个sh -c '…’只是有扩大变量范围的效果,而不需要导出。(参见在bash中的命令对管道中的第二个命令无效之前设置环境变量)