2017-04-19 69 views
0

我想第一次使用bash脚本,并且我使用sed来改变配置文件。我需要编辑的键是非常通用的,并且在整个文件中使用,所以我必须依靠一个部分来知道在哪里“触摸”。使用sed来处理整段文字

所以,如上所述,文件周围有多个部分,由[section name]声明,然后在其下面,您具有该部分的配置,并由一个选项卡缩进。有像enabledtype等密钥在整个文件中使用。

因此,一个完整的部分是这样的:

[backend] 
     # enabled = no 
     # data source = average 
     # type = graphite 
     # destination = localhost 
     # prefix = netdata 
     # hostname = localhost 
     # update every = 10 
     # buffer on failures = 10 
     # timeout ms = 20000 

所以我需要做的是:

  1. 取消对整段
  2. 变化enabled = noenabled = yes
  3. 变化destination对具有端口的IP地址的值(192.168.99.38:2003
  4. hostname的值更改为另一个主机名,可能是机器的主机名($HOSTNAME?)。

事情是,我不知道如何解决这个问题。我已经四处寻找sed多行处理,但我绝对不知道如何仅匹配[backend]部分。这对我来说很新。

帮助将不胜感激。

+0

所以你只需要编辑下面的'[后端]的配置'如果存在与否要编辑的所有部分在[section-name]下面? –

+0

@ k-five只有'[backend]'下的内容,没有别的。对不起,不够清楚, – Aborted

+0

@Inian我看不到你的答案。我之前看到一个,我打算应用它,但现在已经消失了。 – Aborted

回答

1

如您发表评论我:只有什么下[后端],没有别的

您可能会对此感兴趣Perl如果不是只是评论我;我将删除和答案。

说你有这样的文件:

[no-backend] 
     # enabled = no 
     # data source = average 
     # type = graphite 
     # destination = localhost 
     # prefix = netdata 
     # hostname = localhost 
     # update every = 10 
     # buffer on failures = 10 
     # timeout ms = 20000 

[backend] 
     # enabled = no 
     # data source = average 
     # type = graphite 
     # destination = localhost 
     # prefix = netdata 
     # hostname = localhost 
     # update every = 10 
     # buffer on failures = 10 
     # timeout ms = 20000 

[no-backend] 
     # enabled = no 
     # data source = average 
     # type = graphite 
     # destination = localhost 
     # prefix = netdata 
     # hostname = localhost 
     # update every = 10 
     # buffer on failures = 10 
     # timeout ms = 20000 

这一个班轮发现,部分为您提供:

perl -lne '$b=$.; $e=($b+10) if /\[backend\]/;print if $b++<$e' file 

or readable version 
perl -lne 'if(/\[backend\]/){ $b=$.; $e=($b+10); }; if($b++ < $e){ print }' file 

和输出:

[backend] 
     # enabled = no 
     # data source = average 
     # type = graphite 
     # destination = localhost 
     # prefix = netdata 
     # hostname = localhost 
     # update every = 10 
     # buffer on failures = 10 
     # timeout ms = 20000 

,现在改为print you ca ñ修改该条:

s/#//;s/no/yes/;s/(?<=destination =).+$/192.168.99.38:2003/;s/(?<=hostname =).+$/$HOSTNAME/ 

完整的一行

perl -lpe 'if(/\[backend\]/){$b=$.;$e=($b+10);};if($b++<$e){ s/#//;s/no/yes/;s/(?<=destination =).+$/192.168.99.38:2003/;s/(?<=hostname =).+$/\$HOSTNAME/ }' file 

和输出:

[no-backend] 
     # enabled = no 
     # data source = average 
     # type = graphite 
     # destination = localhost 
     # prefix = netdata 
     # hostname = localhost 
     # update every = 10 
     # buffer on failures = 10 
     # timeout ms = 20000 
[backend] 
     enabled = yes 
     data source = average 
     type = graphite 
     destination = 192.168.99.38:2003 
     prefix = netdata 
     hostname = $HOSTNAME 
     update every = 10 
     buffer on failures = 10 
     timeout ms = 20000 

[no-backend] 
     # enabled = no 
     # data source = average 
     # type = graphite 
     # destination = localhost 
     # prefix = netdata 
     # hostname = localhost 
     # update every = 10 
     # buffer on failures = 10 
     # timeout ms = 20000 

,最后检查输出,如果一切良好后,再您可以使用-i选项来使用就地编辑功能,例如:

perl -i.bak -lne '...the rest of the script...' file

.bak仅用于获取旧文件的备份。 (如:file.txt.bak)


UPDATE的评论

perl -lpe '$hn=qx(cat /etc/hostname);chomp $hn;if(/\[backend\]/){$b=$.;$e=($b+10);};if($b++<$e){s/#//;s/no/yes/;s/(?<=destination =).+$/192.168.99.38:2003/;s/(?<=hostname =).+$/$hn/ }' file 

和输出:

... 
... 
[backend] 
     enabled = yes 
     data source = average 
     type = graphite 
     destination = 192.168.99.38:2003 
     prefix = netdata 
     hostname = k-five 
     update every = 10 
     buffer on failures = 10 
     timeout ms = 20000 
... 
... 
+0

我不介意Perl。我很确定它在所有Ubuntu版本上默认安装。但是有一个问题:什么是[无后端]部分? – Aborted

+0

@Aborted默认情况下,大多数Linux发行版都有** Perl **,Ubuntu也是。 '[no-backend]'只是另一个不应该匹配的部分,只是肯定的 –

+0

啊,对不起,我没有得到。非常感谢你的帮助! – Aborted

1

sed不是这种东西的理想工具,但它可以做到:

/^\[.*]$/h 
{G;/\n\[backend\]$/{ 
    s/#// 
    /enabled/s/no/yes/ 
    /destination/s/localhost/whatever/ 
    /hostname/s/localhost/something else/ 
    } 
    s/\n\[.*\]$// 
} 
1

假设文本是CONFIGFILE有是以“[”开头的另一部分,下面的解决方案应该可以工作

sed -i '/\[backend\]/,/\[/{s/#//;s/enabled = no/enabled = yes/;s/\(destination = \)\(.*\)\($\)/\1192\.168\.99\.38\:2003\3/;s/\(hostname = \)\(.*\)\($\)/\1'$HOSTNAME'\3/}' configfile 

我们搜索[backend]和[之间的文本,然后执行封装在{}中的sed命令。我们删除#然后编辑目标以及最终的主机名。

如果有低于后端没有其他的部分,命令更改为:

sed -i '/\[backend\]/,/^$/{s/#//;s/enabled = no/enabled = yes/;s/\(destination = \)\(.*\)\($\)/\1192\.168\.99\.38\:2003\3/;s/\(hostname = \)\(.*\)\($\)/\1'$HOSTNAME'\3/}' configfile