2017-01-24 4 views
0

Abschnitt in der Datei ersetzen habe ich eine Datei, und ich versuche zu Regex, die die Linien zu entfernen, die hat:sed oder perl regex

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

Ich habe versucht, diesen Perl-Befehl zu verwenden, es endet alles auf Entfernen von # Cloud-config bis - Name: docker.service

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

datei.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 
      ... 

Antwort

3

den genauen Text Sie

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

durch Beobachtung zeigen Gegeben Das funktioniert, dass es keine } innerhalb des Textes entfernt werden soll. Es verwendet somit die negierte Zeichenklasse, [^}], die mit einem anderen Zeichen als } übereinstimmt. So mit + passt es alle bis zum ersten }. Siehe hierzu in perlretut und in perlrecharclass. Bitte für andere Texte anpassen.

Oder verwenden

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

die die positive Vorschau(?=...) verwendet. Es ist eine Zero Wide Assertion, was bedeutet, dass es bis dieses Muster entspricht und es nicht konsumiert. Es "sieht" nur so aus, dass es da ist. Sehen Sie es in perlretut. In diesem Fall benötigen wir auch den Modifikator , der . auch zum Newline passt.

Der -0[oct/hex] Schalter stellt den Eingangsdatensatztrenner$/ ein. Die -00 setzt es auf eine leere Zeile und liest damit nach Absätzen, was nicht das ist, was Sie brauchen. Die -0 teilt die Eingabe durch null Zeichen, die sehr unwahrscheinlich ist, in einer Datei zu sein, so dass es normalerweise "funktioniert" für das Lesen der gesamten Datei auf einmal. Aber eine richtige Art, um eine Datei zu schlürfen, ist es, etwas Größeres als und -0777 ist üblich. Siehe Command line switches in perlrun

Hier können Sie -p statt -n verwenden können und dann print fallen, da -p druckt $_.

+0

dank perl -0777 -ne ‚s/Flanell: [^}] +}} //; print 'file.txt funktioniert .. es fehlt nur ein Extra} von Ihrer ursprünglichen Antwort – user1012135

+0

__But eine richtige Art und Weise zu schlürfen eine Datei ist etwas größer als -0400 und -0777__ Gute Erklärung. Wie in den Dokumenten angegeben. –

+0

@ChrisCharley Ja, ich habe diese Seite vielleicht ein paar Mal gesehen :) Ich hatte im Laufe der Zeit gelernt, die Präzision und Autorität der Dokumentation zu schätzen (in Perl) und Standards und dergleichen (in anderen Sprachen). Die meiste Zeit ist es die einzige ultimative Antwort. (In Perl ist das wahre Ultimum natürlich der Quellcode.) – zdim

1

In der Befehlszeile spec -00ne, Sie fragen nach 'Absatz' Modus (zwei Nullen). Ich denke, du willst die Datei schlürfen, wenn ich dein Problem richtig verstehe. Das würde eine Null verwenden.

benutzte ich perl -0777 -pe 's/^\s+flannel:.+?(?=^\s+etcd2)//ms' file.txt zu bekommen, was ich glaube, Sie wollen:

Hinweis die Fahnen ms. m lässt die ^ am Anfang einer 'Zeile' anstelle des Standardverhaltens der Übereinstimmung am Anfang einer 'Zeichenfolge' übereinstimmen. Und der s Flag ermöglicht Punkt (.) Auch Zeilenumbrüche, die in der Lösung, die ich gab, benötigt wird.

#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 
1

Es ist YAML also verwenden Sie einen 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;