我有一个 yaml 文件文件,其中包含ssl_ruleN
其中 N 是 1 到 100 之间的数字。 我想添加每个规则local:cipher_suites.cipher_suites_ruleN
,所以我需要在for中匹配每个规则。 尝试使用 sed,但问题显然是它也与规则 10 和规则 1 匹配。这样,它最终 rule2 也包含来自 rule20 的数据。
和输入文件:
ssl_rule.ssl_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_rule.ssl_rule10: {action: block, dst_networks: 'local:rule_networks_fragment.RoutedNetGrpSelection10',
dst_services: 'local:rule_ports_fragment.PortSelectionSSL', dst_zones: 'local:rule_zones_fragment.ZoneSelectionRouted',
name: ssl_rule10, rid: 10, src_networks: 'local:rule_networks_fragment.RoutedNetGrpSelection10',
src_zones: 'local:rule_zones_fragment.ZoneSelectionRouted'}
ssl_rule.ssl_rule11: {action: block, dst_networks: 'local:rule_networks_fragment.RoutedNetGrpSelection11',
dst_services: 'local:rule_ports_fragment.PortSelectionSSL', dst_zones: 'local:rule_zones_fragment.ZoneSelectionRouted',
name: ssl_rule11, rid: 11, src_networks: 'local:rule_networks_fragment.RoutedNetGrpSelection11',
src_zones: 'local:rule_zones_fragment.ZoneSelectionRouted'}
ssl_rule.ssl_rule12: {action: block_with_reset, dst_networks: 'local:rule_networks_fragment.RoutedNetGrpSelection12',
dst_services: 'local:rule_ports_fragment.PortSelectionSSL', dst_zones: 'local:rule_zones_fragment.ZoneSelectionRouted',
name: ssl_rule12, rid: 12, src_networks: 'local:rule_networks_fragment.RoutedNetGrpSelection12',
src_zones: 'local:rule_zones_fragment.ZoneSelectionRouted'}
ssl_rule.ssl_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
我尝试过:
for i in `seq 1 53`;do
sed "/ssl_rule.ssl_rule${i}[:] /,/action:/{s/action:/cipher_suites: 'local:cipher_suites.cipher_suites_rule$i', action:/g;}" -i cucu.yaml
done
但它以某种方式混淆了规则,规则 10 包含规则 1 等等。请注意,我使用了/start/,/end/模式,因为技术因为有时规则跨越几行,我也想匹配它们(示例 rule25 )
预期输出(每个规则内部要包含local:cipher_suites.cipher_suites_ruleN
,N
与ruleN
相对应)
ssl_rule.ssl_rule1: {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'}
如注释中所述,您显然不希望sed
从行匹配ssl_rule
修改到下一个行匹配action:
此外,多次遍历文件并在每次传递时执行一次替换是非常低效和不优雅的。在大多数情况下,您应该告诉sed
要对整个文件执行的操作。
为了在其中一个匹配规则之后立即匹配下一个action:
行,我会切换到 Awk,这使得这种事情变得非常容易。
awk '/^ssl_rule.ssl_rule/ { r = 0 + substr($1, 18); n = (r >= 1 && r <= 53) }
n && /action:/ { sub(/action:/, "cipher_suites: 47local:cipher_suites.cipher_suites_rule" r " 47, action:/"); n = 0} 1' cucu.yaml >cucu.tmp &&
mv cucu.tmp cucu.yaml
回到一个sed
答案,只是为了将一些松散的末端联系在一起。
正则表达式([1-9]|[1-4][0-9]|5[0-3)
匹配数字 1 到 53。 括号还可以方便地捕获匹配的数字,因此我们可以在替换字符串中使用1
来引用它。
sed -i '/ssl_rule.ssl_rule([1-9]|[1-4][0-9]|5[0-3): /s/action:/cipher_suites: '"'"'local:cipher_suites.cipher_suites_rule1'"'"', action:/' -i cucu.yaml
我在这个脚本周围切换到单引号,然后要求文字单引号用一个稍微奇怪的'"'"'
序列表示,该序列关闭当前的单引号表达式,添加一个文字单引号(用双引号引号引号以将其从外壳中转义)并打开一个新的单引号表达式,所有这些都彼此相邻。
不需要反斜杠转义冒号,但应该对点进行转义以使其字面匹配(未转义的点匹配任何字符)。