Regex sed或perl正则表达式替换文件中的节
我有一个文件,正在尝试使用正则表达式删除以下行:Regex sed或perl正则表达式替换文件中的节,regex,perl,sed,Regex,Perl,Sed,我有一个文件,正在尝试使用正则表达式删除以下行: flannel: interface: $private_ipv4 etcd_endpoints: {{ .ETCDEndpoints }} 我尝试使用这个perl命令,它最终删除了#cloud config中的所有内容,直到--name:docker.service perl -i -00ne 'print unless /(flannel:).*([^ ]+).*([^ ]+).*}}/' file.txt file.tx
flannel:
interface: $private_ipv4
etcd_endpoints: {{ .ETCDEndpoints }}
我尝试使用这个perl命令,它最终删除了#cloud config中的所有内容,直到--name:docker.service
perl -i -00ne 'print unless /(flannel:).*([^ ]+).*([^ ]+).*}}/' 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
...
在命令行spec
-00ne
中,要求使用“段落”模式(两个零)。如果我没弄错你的问题,我想你应该把文件弄脏。这将使用一个零
我使用了perl-0777-pe的//^\s+flannel:.+?(?=^\s+etcd2)//ms的file.txt
来获得我认为您想要的:
注意标志ms
m
使^
在“行”开头匹配,而不是在“字符串”开头匹配的默认行为。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
在命令行spec
-00ne
中,要求使用“段落”模式(两个零)。如果我没弄错你的问题,我想你应该把文件弄脏。这将使用一个零
我使用了perl-0777-pe的//^\s+flannel:.+?(?=^\s+etcd2)//ms的file.txt
来获得我认为您想要的:
注意标志ms
m
使^
在“行”开头匹配,而不是在“字符串”开头匹配的默认行为。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
给定您显示的确切文本
perl -0777 -ne 's/flannel:[^}]+}//; print' file.txt
这是通过观察到要删除的文本中没有}
来实现的。因此,它使用求反字符类[^}]
,该类匹配除}
以外的任何字符。因此,对于+
,它将所有内容匹配到第一个}
。看看这个,然后。
请调整其他文本
或使用
perl -0777 -ne 's/flannel:.+?(?=etcd2:)+//s; print' file.txt
它使用正向前瞻(?=…)
。它是一个零宽度断言,意味着它匹配该模式,并且不使用它。它只是“看起来”(断言)它就在那里。看到了。在这种情况下,我们还需要修饰符/s
,它使
也与换行符匹配
-0[oct/hex]
开关设置输入记录分隔符$/
。-00
将其设置为空行,因此按段落阅读,这不是您需要的。-0
通过null
字符分割输入,该字符不太可能出现在文件中,因此通常一次读取整个文件“有效”。但是,正确地读取文件的方法是指定大于-0400
的任何内容,而-0777
是惯例。看
在这里,您可以使用
-p
而不是-n
,然后删除print
,因为-p
会打印$\uu
,只要您显示的是准确的文本
perl -0777 -ne 's/flannel:[^}]+}//; print' file.txt
这是通过观察到要删除的文本中没有}
来实现的。因此,它使用求反字符类[^}]
,该类匹配除}
以外的任何字符。因此,对于+
,它将所有内容匹配到第一个}
。看看这个,然后。
请调整其他文本
或使用
perl -0777 -ne 's/flannel:.+?(?=etcd2:)+//s; print' file.txt
它使用正向前瞻(?=…)
。它是一个零宽度断言,意味着它匹配该模式,并且不使用它。它只是“看起来”(断言)它就在那里。看到了。在这种情况下,我们还需要修饰符/s
,它使
也与换行符匹配
-0[oct/hex]
开关设置输入记录分隔符$/
。-00
将其设置为空行,因此按段落阅读,这不是您需要的。-0
通过null
字符分割输入,该字符不太可能出现在文件中,因此通常一次读取整个文件“有效”。但是,正确地读取文件的方法是指定大于-0400
的任何内容,而-0777
是惯例。看
在这里,您可以使用
-p
而不是-n
,然后删除print
,因为-p
打印$。是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;
#/usr/bin/env perl
严格使用;
使用警告;
使用YAML::XS;
使用数据::转储程序;
#是神奇的文件句柄,它读取命令行或STDIN上的文件。
#很像grep/sed/awk。
my$conf=Load(do{local$/;});
#打印以进行调试。
打印转储程序$conf;
#删除不需要的密钥。
删除$conf->{coreos}{flannel};
#将输出打印到标准输出。
#如果您愿意,您可以将其破解到就地编辑中
#需要。
打印转储$conf;
这是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;
#/usr/bin/env perl
严格使用;
使用警告;
使用YAML::XS;
使用数据::转储程序;
#是神奇的文件句柄,它读取命令行或STDIN上的文件。
#很像grep/sed/awk。
my$conf=Load(do{local$/;});
#打印以进行调试。
打印转储程序$conf;
#删除不需要的密钥。
删除$conf->{coreos}{flannel};
#将输出打印到标准输出。
#如果您愿意,您可以将其破解到就地编辑中
#需要。
打印转储$conf;
谢谢perl-0777-ne的/flannel:[^}]+}//;print'file.txt worked..刚从您的原始回答中丢失了一个额外的},但是正确的方法是指定大于-0400和-0777的任何内容,这是一个很好的解释。正如文档中所述。@ChrisCharley是的,我可能已经看过几次了:)随着时间的推移,我学会了欣赏文档(Perl)和标准等(其他语言)的准确性和权威性。大多数情况下,这是唯一的最终答案。(在Perl中,真正的终极版当然是源代码。)感谢Perl-0777-ne的/flannel:[^}]+}//;print'file.txt worked..刚从您的原始回答中丢失了一个额外的},但是正确的方法是指定大于-0400和-0777的任何内容,这是一个很好的解释。如文件所述。@chrischalley是的,我可能已经看过那一页好几次了