2013-11-28 110 views
25

我使用下面的命令sed在配置文件來替換一些參數如何在SED添加一行:如果沒有找到匹配

sed -i 's/^option.*/option=value/g' /etc/fdm_monitor.conf 

現在我有一個問題。如果該行不存在,我想將其添加到文件的底部。

我打電話給一個popen出C程序。我嘗試使用awk

回答

41

試試這個:

grep -q '^option' file && sed -i 's/^option.*/option=value/' file || echo 'option=value' >> file 
+0

非常容易和有用! – JohnyTex

1

這是它使用

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 

/^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執行編輯: 作爲一個班輪:

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 
+0

我需要一個襯墊,因爲我送這是從C PROGRAMM系統調用。 – Evilmachine

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 
3

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

這似乎並不奏效。它在每行之後添加「option = value」。不知道它是如何得到兩個upvotes。你可以做'$ aoption = value',但是我似乎無法在前一個匹配項上做出這樣的條件,所以無論如何它只是追加到最後。 – sosiouxme

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

負荷都在緩衝區中的文件,到了最後,將所有發生和如果沒有變化發生時,添加到末尾

2
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 
3

作爲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]是您的輸入file。它被打開並寫入END塊的for循環中。在END塊中輸出file代替了對諸如sponge之類的實用程序的需求,或者寫入臨時文件,然後將臨時文件寫入file

數組a[]的兩個賦值將所有輸出行累加到aif(!f)a[++n]=s如果主awk循環在file中找不到option,則附加新的option=value

爲了便於閱讀,我添加了一些空格(不是很多),但是在整個awk程序中只需要一個空格,即print之後的空格。 如果file包括# comments它們將被保留。

0

我通過設置變量來闡述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 '...'只是有擴大變量的作用域,而不需要一個export的效果。 (見Setting an environment variable before a command in bash not working for second command in a pipe

1

這裏是一個內聯的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 
相關問題