如何用sed/awk在YAML的ssl_ruleN中插入对应cipher_suites配置?
解决YAML中批量为ssl_ruleN插入对应cipher_suites配置的匹配混淆问题
你的问题核心是正则匹配没有限定规则编号的边界,导致ssl_rule1会误匹配ssl_rule10/ssl_rule11等,再加上部分规则跨多行,普通的sed范围匹配容易失效。下面给你两个可靠的解决方法:
方法一:改进Sed命令,精准匹配+处理跨多行
通过给正则添加数字边界限定,确保只匹配正好的ssl_ruleN,同时用循环读取多行直到找到action:,处理跨多行规则:
for i in $(seq 1 53); do # 备份原文件为cucu.yaml.bak,防止误操作 sed -E -i.bak "/ssl_rule\.ssl_rule${i}([^0-9]|$)/{ # 循环读取行,直到找到包含action:的行 :multiline_loop /action:/!{N; b multiline_loop} # 在action:前插入对应编号的cipher_suites配置 s/(action:)/cipher_suites: 'local:cipher_suites.cipher_suites_rule${i}', \1/ }" cucu.yaml done
关键细节:
ssl_rule\.ssl_rule${i}([^0-9]|$):确保匹配的ssl_ruleN后面要么不是数字,要么到行尾,彻底避免rule1匹配rule10的问题:multiline_loop+N; b multiline_loop:如果当前行没有action:,就把下一行合并进来,直到找到目标字段,完美处理跨多行的规则-E启用扩展正则,让语法更简洁;-i.bak会自动备份原文件,更安全
方法二:用Awk一次性处理所有规则(推荐)
Awk天生适合处理结构化文本,不需要循环遍历每个编号,一次扫描就能完成所有操作,更高效且不易出错:
awk ' # 把每个ssl_ruleN:作为记录分隔符 BEGIN { RS = "ssl_rule\\.ssl_rule[0-9]+:"; ORS = "" } # 跳过第一个空记录(文件开头到第一个ssl_ruleN:之间的内容) NR > 1 { # 从记录分隔符中提取规则编号N match(RT, /ssl_rule([0-9]+):/, match_result) rule_num = match_result[1] # 输出规则头,然后在action:前插入对应cipher_suites printf "%s", RT sub(/(action:)/, "cipher_suites: '\''local:cipher_suites.cipher_suites_rule"rule_num"'\'', \\1") print $0 } ' cucu.yaml > cucu_temp.yaml && mv cucu_temp.yaml cucu.yaml
优势:
- 不需要循环,一次处理所有1-100的规则,效率更高
- 自动识别每个规则的编号,完全避免匹配混淆问题
- 天然支持跨多行规则,不需要额外处理行合并逻辑
验证效果
以你提供的输入为例,处理后ssl_rule1会变成:
ssl_rule.ssl_rule1: {cipher_suites: 'local:cipher_suites.cipher_suites_rule1', action: block, dst_networks: 'local:rule_networks_fragment.RoutedNetGrpSelection1', dst_services: 'local:rule_ports_fragment.PortSelectionSSL', dst_zones: 'local:rule_zones_fragment.ZoneSelectionRouted', name: ssl_rule1, rid: 1, src_networks: 'local:rule_networks_fragment.RoutedNetGrpSelection1', src_zones: 'local:rule_zones_fragment.ZoneSelectionRouted'}
跨多行的ssl_rule25会变成:
ssl_rule.ssl_rule25: cipher_suites: 'local:cipher_suites.cipher_suites_rule25', action: decrypt_resign decryption_certs: ['local:internal_ca_certificate.Internal_Cert_4096'] dst_networks: local:rule_networks_fragment.RoutedNetGrpSelection25 dst_services: local:rule_ports_fragment.PortSelectionSSL dst_zones: local:rule_zones_fragment.ZoneSelectionRouted name: ssl_rule25 rid: 25 src_networks: local:rule_networks_fragment.RoutedNetGrpSelection25 src_zones: local:rule_zones_fragment.ZoneSelectionRouted
内容的提问来源于stack exchange,提问作者dubsauce




