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

include "/configs/projectname.conf"

到一个名为lighttpd.conf的文件

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

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


当前回答

你可以使用这个函数来查找和搜索配置更改:

#!/bin/bash

#Find and Replace config values
find_and_replace_config () {
   file=$1
   var=$2
   new_value=$3
   awk -v var="$var" -v new_val="$new_value" 'BEGIN{FS=OFS="="}match($1, "^\\s*" var "\\s*") {$2=" " new_val}1' "$file" > output.tmp && sudo mv output.tmp $file
}

find_and_replace_config /etc/php5/apache2/php.ini max_execution_time 60

其他回答

下面是一个单行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

使用grep得到的答案是错误的。你需要添加一个-x选项来匹配整行,否则像#text to add这样的行在寻找要添加的文本时仍然会匹配。

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

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

保持简单就好:)

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的建议。

使用awk

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

下面是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