Reputation: 81
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 -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
...
Upvotes: 0
Views: 463
Reputation: 66883
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.
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. In this case we also need the modifier /s
, which makes .
match the newline, too.
The -0[oct/hex]
switch sets the input record separator $/
. The -00
sets it to an empty line thus reading by paragraphs, which isn't what you need. 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. But a proper way to slurp a file is to specify anything greater than -0400
and -0777
is customary. See Command line switches in perlrun
Here you can use -p
instead of -n
and then drop print
, since -p
prints $_
.
Upvotes: 3
Reputation: 53478
It's YAML so use a YAML parser.
#!/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;
Upvotes: 1
Reputation: 6573
In your command line spec -00ne
, you are asking for 'paragraph' mode (two zeros). 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:
Note the flags ms
. m
makes the ^
match at the beginning of a 'line' instead of the default behavior of matching at the beginning of a 'string'. And the s
flag allows dot (.) to also match newlines which is needed in the solution I gave.
#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
Upvotes: 1