如何替换两个或多个关键字之间的段落

如何替换两个或多个关键字之间的段落

我正在尝试替换关键字之间的完整段落。

由此 :

   port: 6666
    socks-port: 6699
    redir-port: 6669
    allow-lan: true
    mode: Rule
    log-level: info
    external-controller: 0.0.0.0:9090
    
    dns:
  enable: true
  ipv6: false
  # listen: 0.0.0.0:53
  # enhanced-mode: fake-ip
  nameserver:
    - 223.5.5.5
    - 114.114.114.114
  #  - 'tls://dns.rubyfish.cn:853'
  #fallback:
  #  - 'tcp://208.67.222.222:443'
  #  - 'tls://1.0.0.1:853'
  #  - 8.8.8.8
    proxies:
      - type: ss
        server: test.com
        
    proxy-groups:
    
      - name: 

答案1

如果您的替换文本file1如下所示(添加最后一行)

dns:
   enable: true
   enhanced-mode: redir-host # 或 fake-ip
   listen: 0.0.0.0:53
   nameserver:
      - 223.5.5.5
experimental:
   interface-name: Ethernet # 物理网卡名称
proxies:

稍微研究了一下,sed地址范围似乎是非贪婪的,所以这是可行的

sed -e "/^    proxies:/ r file1" -e "/dns:/,/proxies:/d" file

演练

r读取并在匹配后将file1其添加到原始中file/^ proxies:/

sed -e "/^    proxies:/ r file1"

/dns:/然后重新处理整个事情,捕获从第一个匹配到,第一个匹配的行范围/proxies:/d删除它们

    -e "/dns:/,/proxies:/d" file

sed上面有一个有用的资源格里莫尔

编辑更新评论

其他proxies:行与您的目标的区别在于行首有 4 个空格(其他行有超过 4 个)。如果您锚定要包含的替换项^,那么它只会选择您感兴趣的替换项,因此

sed -e "/^    proxies:/ r file1" -e "/dns:/,/proxies:/d" file

通过我上面的插入,file1这会产生

   port: 6666
    socks-port: 6699
    redir-port: 6669
    allow-lan: true
    mode: Rule
    log-level: info
    external-controller: 0.0.0.0:9090
    
dns:
   enable: true
   enhanced-mode: redir-host # 或 fake-ip
   listen: 0.0.0.0:53
   nameserver:
      - 223.5.5.5
experimental:
   interface-name: Ethernet # 物理网卡名称
proxies:
      - type: ss
        server: test.com
        
    proxy-groups:
    
      - name: 

答案2

sed posixly 我们就可以实现所需要的了。

sed -e '
  /dns:/,/proxies:/!b
  /dns:/r file1
  /proxies:/!d
' file

解释:

  • 按原样打印范围之外的行。
  • 范围是 DNS 线路开始到代理结束。
  • 在范围内,将 dns 行插入到 stdout 流中。
  • 删除范围内除代理之外的所有行
  • 由于读取命令不触及模式空间,因此删除 dns 仍将打印读取的文件 file1

答案3

假设file1包含您的替换文本:

$ cat file1
dns:
   enable: true
   enhanced-mode: redir-host # 或 fake-ip
   listen: 0.0.0.0:53
   nameserver:
      - 223.5.5.5
experimental:
   interface-name: Ethernet # 物理网卡名称

file2您想要应用更改的文件,该文件适用于每个 UNIX 机器上任何 shell 中使用任何 awk 的任何文本输入:

$ cat tst.awk
NR == FNR { new = (NR>1 ? new ORS : "") $0; next }
$1 == "dns:" { print new; f=1 }
$1 == "proxies:" { f=0 }
!f

$ awk -f tst.awk file1 file2
   port: 6666
    socks-port: 6699
    redir-port: 6669
    allow-lan: true
    mode: Rule
    log-level: info
    external-controller: 0.0.0.0:9090

dns:
   enable: true
   enhanced-mode: redir-host # 或 fake-ip
   listen: 0.0.0.0:53
   nameserver:
      - 223.5.5.5
experimental:
   interface-name: Ethernet # 物理网卡名称
    proxies:
      - type: ss
        server: test.com

    proxy-groups:

      - name: 

相关内容