Bash 使用sed处理完整的文本部分
我第一次尝试bash脚本,但我一直坚持使用Bash 使用sed处理完整的文本部分,bash,ubuntu,sed,Bash,Ubuntu,Sed,我第一次尝试bash脚本,但我一直坚持使用sed来更改配置文件。我需要编辑的键非常通用,在整个文件中都会用到,所以我必须依靠一个部分来知道在哪里进行“触摸” 因此,如前所述,文件周围有多个部分,由[section name]声明,然后在它下面,有该部分的配置,由一个选项卡缩进。有像enabled,type等键,它们在整个文件中使用 因此,完整的部分如下所示: [backend] # enabled = no # data source = average
sed
来更改配置文件。我需要编辑的键非常通用,在整个文件中都会用到,所以我必须依靠一个部分来知道在哪里进行“触摸”
因此,如前所述,文件周围有多个部分,由[section name]
声明,然后在它下面,有该部分的配置,由一个选项卡缩进。有像enabled
,type
等键,它们在整个文件中使用
因此,完整的部分如下所示:
[backend]
# enabled = no
# data source = average
# type = graphite
# destination = localhost
# prefix = netdata
# hostname = localhost
# update every = 10
# buffer on failures = 10
# timeout ms = 20000
所以我需要做的是:
enabled=no
更改为enabled=yes
destination
的值更改为带有端口的IP地址(192.168.99.38:2003
)hostname
的值更改为另一个主机名,可能是机器的主机名($hostname
?)问题是,我根本不知道如何解决这个问题。我已经查找了sed多行处理,但我确实不知道如何仅匹配
[backend]
部分。这对我来说是非常新的。sed
不是这类东西的理想工具,但它可以做到:
/^\[.*]$/h
{G;/\n\[backend\]$/{
s/#//
/enabled/s/no/yes/
/destination/s/localhost/whatever/
/hostname/s/localhost/something else/
}
s/\n\[.*\]$//
}
sed
不是这类东西的理想工具,但它可以做到:
/^\[.*]$/h
{G;/\n\[backend\]$/{
s/#//
/enabled/s/no/yes/
/destination/s/localhost/whatever/
/hostname/s/localhost/something else/
}
s/\n\[.*\]$//
}
正如你评论我的那样:只有[后端]下的内容,没有其他内容
您可能会对使用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
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
现在,您可以使用以下内容修改该部分,而不是打印:
s/#//;s/no/yes/;s/(?<=destination = ).+$/192.168.99.38:2003/;s/(?<=hostname = ).+$/$HOSTNAME/
最后,在检查输出是否一切正常后,您可以使用-i
选项使用在位编辑功能,如:
perl-i.bak-lne'…脚本的其余部分…'文件
.bak仅用于获取旧文件的备份。(如:file.txt.bak)
更新以获取您的评论 正如你评论我的那样:只有[后端]下的内容,没有其他内容 您可能会对使用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
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
现在,您可以使用以下内容修改该部分,而不是打印:
s/#//;s/no/yes/;s/(?<=destination = ).+$/192.168.99.38:2003/;s/(?<=hostname = ).+$/$HOSTNAME/
最后,在检查输出是否一切正常后,您可以使用-i
选项使用在位编辑功能,如:
perl-i.bak-lne'…脚本的其余部分…'文件
.bak仅用于获取旧文件的备份。(如:file.txt.bak)
更新以获取您的评论
假设文本在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]和[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
假设文本在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]和[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
因此,您只想编辑
[backend]
下的配置(如果存在或不存在),您想编辑[section name
]下的所有部分?@k-five仅编辑[backend]下的部分
,没有其他内容。抱歉说得不够清楚,@Inian我看不到你的答案。我之前看到了一个答案,我打算应用它,但现在它不见了。@Aborted:删除了它,因为它不满足你的要求,只满足[backend]下的内容
条件,立即修复您是否接受Perl one Liner?您是否只想编辑[后端]
下的配置(如果存在或不存在)您想编辑[部分名称
]下的所有部分?@k-five仅编辑[后端]下的内容
,没有其他内容。抱歉说得不够清楚,@Inian我看不到你的答案。我之前看到了一个答案,我打算应用它,但现在它不见了。@Aborted:删除了它,因为它不满足你的要求,只满足[backend]下的内容
条件,现在修复它您是否接受Perl one Line我不介意Perl。我相当确定它默认安装在所有Ubuntu版本上。但有一个问题:[无后端]
部分是什么?@大多数Linux发行版默认都有Perl和Ubuntu。[无后端]
只是另一个不应该匹配的部分,当然,很抱歉,我没有得到。非常感谢您的帮助!@没问题:)另一个问题:我不想要文本$HOSTNAME
字符串。$HOSTNAME
将是一个包含系统主机名的系统变量。您的Perl脚本是否连接这个变量还是将文字表达式放在那里?我不介意Perl。我相当确定它默认安装在所有Ubuntu版本上。但有一个问题:[无后端]
部分是什么?@大多数Linux发行版默认都有Perl和Ubuntu。[无后端]
只是另一个不应该匹配的部分,当然,很抱歉,我没有得到。非常感谢您的帮助!@没问题:)另一个问题:我不想要文本$HOSTNAME
字符串。$HOSTNAME
将是一个包含系统主机名的系统变量。您的Perl脚本是否连接这个变量或把li