我想在特定模式匹配后删除 "#"
。
例如:
在下面的代码中,我将为 "SOME DESC"
grep
。我希望在 "SOME DESC"
上方和下方注释的所有行都取消注释。
现有代码
#define service {
# hostgroup_name hmaster_hosts
# use local-service
# servicegroups SOME_GROUP
# service_description SOME DESC : service Service
# check_command check_nrpe!check_something
#}
去掉“#”后
define service {
hostgroup_name hmaster_hosts
use local-service
servicegroups SOME_GROUP
service_description SOME DESC : service Service
check_command check_nrpe!check_something
}
我尝试了以下代码来进行更改。
sed -i 's/#define service {/define service {/g' services.cfg
sed -i 's/# hostgroup_name / hostgroup_name /' services.cfg
sed -i 's/# use / use /' services.cfg
sed -i 's/# servicegroups/ servicegroups/' services.cfg
sed -i 's/# service_description / service_description /' services.cfg
sed -i 's/# check_command / check_command /' services.cfg
sed -i 's/#}/}/g' services.cfg
但是#
在代码中的位置是不确定的,可以是#hostgroup_name
或者#hostgroup_name
或者#hostgroup_name
所以我的方法适用于部分代码。我想知道无论 #
最佳答案
如果您有 GNU awk
,您可以尝试以下操作:
awk -v search='SOME DESC' -v RS='(^|\n)#define service \\{[^}]*\\#\\}\n' '
index(RT, search) { RT = gensub("(^|\n)#", "\\1", "g", RT) }
{ printf "%s%s", $0, RT }
' file
上面假设注释行直接以 #
开始,代码紧跟在后面,就像问题中的示例输入一样。有关适用于可变数量空白的变体解决方案,请参阅底部。
这假定感兴趣的注释行是注释define service { ... }
行的 block ,如果在其中找到搜索字符串,则应将其作为一个整体取消注释 block 。
-v search='SOME DESC'
传递要搜索的文字字符串作为 Awk 变量search
。-v RS='(^|\n)#define service\\{[^}]*\\#\\}\n'
定义RS
,输入记录 分隔符,作为正则表达式,以注释掉的define service {
行开始,以注释掉的结束
行,后跟一个换行符。这意味着当前记录的
<$0
中报告的数据包含每个感兴趣的 block 之前的行。但是,GNU 公开了
RS
中的正则表达式通过(非标准)变量RT
匹配的实际记录终止符(分隔符)。因此,RT
的值包含每次迭代中感兴趣的 block 。
index(RT, search)
返回当前 block 内搜索字符串位置的从 1 开始的索引,如果 block 不包含搜索字符串,则返回 0。当用作模式( bool 条件)时,关联的操作({...}
)因此仅在 block 包含搜索字符串时执行。RT = gensub("(^|\n)#", "\\1", "g", RT)
删除注释字符。 (#
) 从 block 中所有行的最开始。
请注意,gensub()
是一个特定于 GNU 的函数,它特别允许使用引用来捕获组(\1
指的是捕获组(^|\n)
匹配;需要额外的\
,因为awk
的string解析过程\
-前缀转义序列)。
{ printf "%s%s", $0, RT }
打印当前记录 ($0
),后跟 - 可能未注释的 - block 。
适用于可变数量空白的变体:
awk -v search='SOME DESC' -v RS='(^|\n)[[:blank:]]*#[[:blank:]]*define[[:blank:]]+service[[:blank:]]+\\{[^}]*\\#[[:blank:]]*\\}\n' '
index(RT, search) { RT = gensub("(^|\n)[[:blank:]]*#", "\\1", "g", RT) }
{ printf "%s%s", $0, RT }
' file
这与上面的解决方案基本相同,除了 #
前后的(可能为空)空格/制表符匹配([[:blank:]]*
),以及 define
行 ([[:blank:]]+
) 的标记之间的可变长度的非空运行。
关于linux - 如何在 shell 脚本中删除模式匹配前后的特定字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41427045/