简体   繁体   English

sed或perl regex替换文件中的部分

[英]sed or perl regex replace section in file

I have a file, and am trying to regex to remove the the lines that has: 我有一个文件,正在尝试正则表达式删除具有以下内容的行:

flannel:
    interface: $private_ipv4
    etcd_endpoints: {{ .ETCDEndpoints }}

I tried to to use this perl command, it ends up removing everything from #cloud-config till -- name: docker.service 我尝试使用此perl命令,最终将所有内容从#cloud-config删除,直到-名称:docker.service

perl -i -00ne 'print unless /(flannel:).*([^ ]+).*([^ ]+).*}}/' file.txt

file.txt: file.txt:

#cloud-config
coreos:
  update:
    reboot-strategy: "off"
  flannel:
    interface: $private_ipv4
    etcd_endpoints: {{ .ETCDEndpoints }}
  etcd2:
    name: controller
    advertise-client-urls: http://$private_ipv4:2379
    initial-advertise-peer-urls: http://$private_ipv4:2380
    listen-client-urls: http://0.0.0.0:2379
    listen-peer-urls: http://0.0.0.0:2380
    initial-cluster: controller=http://$private_ipv4:2380
  units:
    - name: etcd2.service
      command: start
      runtime: true

    - name: docker.service
      drop-ins:
        - name: 40-flannel.conf
          content: |
            [Unit]
            Requires=flanneld.service
            After=flanneld.service
            [Service]
            EnvironmentFile=/etc/kubernetes/cni/docker_opts_cni.env
            ...

Given the exact text you show 根据您显示的确切文字

perl -0777 -ne 's/flannel:[^}]+}//; print' file.txt

This works by observation that there is no } inside the text to be removed. 这是通过观察到要删除的文本中没有}起作用的。 It thus uses the negated character class , [^}] which matches any character other than } . 因此,它使用否定的字符类 [^}]来匹配}以外的任何字符。 So with + it matches all up to the first } . 因此,使用+可以匹配第一个} See this in perlretut and in perlrecharclass . 在perlretutperlrecharclass中看到此内容 Please adjust for other text. 请调整其他文字。

Or use 或使用

perl -0777 -ne 's/flannel:.+?(?=etcd2:)+//s; print' file.txt

which uses the positive lookahead (?=...) . 使用正向前瞻 (?=...) It is a zero width assertion , meaning that it matches up to that pattern and does not consume it. 这是一个零宽度断言 ,这意味着它匹配该模式和不消耗它。 It just "looks" (asserts) that it's there. 它只是“看起来”(断言)它在那里。 See it in perlretut . 在perlretut中看到它。 In this case we also need the modifier /s , which makes . 在这种情况下,我们还需要使用/s 修饰符 ,即. match the newline, too. 也匹配换行符。

The -0[oct/hex] switch sets the input record separator $/ . -0[oct/hex]开关设置输入记录分隔符 $/ The -00 sets it to an empty line thus reading by paragraphs, which isn't what you need. -00将其设置为空行,从而按段落读取,这不是您所需要的。 The -0 splits input by null character, which is very unlikely to be in a file so it normally "works" for reading the whole file at once. -0null字符分割输入,这是不太可能出现在文件中的,因此通常它可以“工作”以一次读取整个文件。 But a proper way to slurp a file is to specify anything greater than -0400 and -0777 is customary. 但要发出声音文件的正确方法是指定任何大于-0400-0777习惯。 See Command line switches in perlrun 请参见perlrun中的命令行开关

Here you can use -p instead of -n and then drop print , since -p prints $_ . 在这里,您可以使用-p代替-n ,然后删除print ,因为-p打印$_

In your command line spec -00ne , you are asking for 'paragraph' mode (two zeros). 在命令行规范-00ne ,您要求的是“段落”模式(两个零)。 I think you want to slurp the file if I'm understanding your problem correctly. 如果我正确理解您的问题,我认为您想对文件进行处理。 That would use one zero. 那将使用一个零。

I used perl -0777 -pe 's/^\\s+flannel:.+?(?=^\\s+etcd2)//ms' file.txt to get what I think you want: 我用perl -0777 -pe 's/^\\s+flannel:.+?(?=^\\s+etcd2)//ms' file.txt来获取我认为您想要的:

Note the flags ms . 注意标记ms m makes the ^ match at the beginning of a 'line' instead of the default behavior of matching at the beginning of a 'string'. m在“行”的开头使^匹配,而不是在“字符串”的开头进行匹配的默认行为。 And the s flag allows dot (.) to also match newlines which is needed in the solution I gave. 并且s标志允许点(。)也可以匹配换行符,这在我给出的解决方案中是必需的。

#cloud-config
coreos:
  update:
    reboot-strategy: "off"
  etcd2:
    name: controller
    advertise-client-urls: http://$private_ipv4:2379
    initial-advertise-peer-urls: http://$private_ipv4:2380
    listen-client-urls: http://0.0.0.0:2379
    listen-peer-urls: http://0.0.0.0:2380
    initial-cluster: controller=http://$private_ipv4:2380
  units:
    - name: etcd2.service
      command: start
      runtime: true

    - name: docker.service
      drop-ins:
        - name: 40-flannel.conf
          content: |
            [Unit]
            Requires=flanneld.service
            After=flanneld.service
            [Service]
            EnvironmentFile=/etc/kubernetes/cni/docker_opts_cni.env

It's YAML so use a YAML parser. 它是YAML,因此请使用YAML解析器。

#!/usr/bin/env perl
use strict;
use warnings;

use YAML::XS;
use Data::Dumper;

# <> is the magic file handle, it reads files on command line or STDIN. 
# much like grep/sed/awk do.     
my $conf = Load ( do { local $/; <> } );
#print for debugging. 
print Dumper $conf;

#delete the key you don't want. 
delete $conf->{coreos}{flannel};

#print output to STDOUT. 
#You can hack this into in place editing if you
#want. 
print Dump $conf;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM