使用sed处理文本的完整部分

时间:2017-04-19 10:44:44

标签: bash ubuntu sed

我第一次尝试使用bash脚本,而且我仍然坚持使用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 = no更改为enabled = yes
  3. destination的值更改为包含端口(192.168.99.38:2003)的IP地址
  4. hostname的值更改为其他主机名,也就是机器的主机名($HOSTNAME?)。
  5. 事情是,我不确定如何解决这个问题。我一直在寻找sed多线处理,但我绝对不知道如何匹配[backend]部分。这对我来说很新鲜。

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分: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

现在代替打印,您可以使用以下内容修改该部分:

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)

更新 以发表评论

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
...
...

答案 2 :(得分: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