2016-11-23 5 views
-1

Ich versuche, ein Perl-Skript zu schreiben, das ein paar Zeilen Text durch ein paar andere Zeilen ersetzt, ich bin ein Perl-Neuling, schätze jede Hilfe.perl regex multiline

Need

'ENTITLEMENT_EVS_V', 
NULL, 
NULL, 

mit ersetzen:

'ENTITLEMENT_EVS_V', 
ENTITLEMENT_CATEGORY_CODE, 
6, 

Ich bin nicht in der Lage dies zu tun, vor allem den Regex Teil. Ich habe versucht, viele Dinge, aber das Skript liegt derzeit bei:

#!/usr/bin/env perl 
my ($lopen_fh, $lwrite_fh); 

# my $l_reg_evs = qq{ 
#'ENTITLEMENT_EVS_V', 
#NULL, 
#NULL, 
#}; 
my $l_reg_evs = qr/(\'ENTITLEMENT_EVS_V\', 
        NULL, 
        NULL, 
        )/; 


     my $l_evs=qq{ 
        'ENTITLEMENT_EVS_V', 
         ENTITLEMENT_CATEGORY_CODE, 
         6, 
        }; 

open ($lopen_fh, '<', "/home/cbdev2/imp/dev/src/deli/entfreeunits/config/entfreeunits/stubs/DirectVariables_evEntlCategory.exp") or die $!; 
open ($lwrite_fh, '>', "/home/cbdev2/imp/dev/src/deli/entfreeunits/config/entfreeunits/stubs/DirectVariables_evEntlCategory.new.exp") or die $!; 

while(<$lopen_fh>) { 
    $_ =~ s/$l_reg_evs/$l_evs/m; 
    print $lwrite_fh $_; 
} 

close $lopen_fh; 
close $lwrite_fh; 
+3

Durch die Datei Zeile für Zeile zu lesen, man kann nie die ganze Reihe sehen zu ersetzen. – choroba

Antwort

1

Ich denke, ich würde so etwas schreiben. Er erwartet, dass Sie den Pfad zu der Eingabedatei als Parameter in der Befehlszeile ein und druckt das Ergebnis

auf stdout

es alle folgenden erfordert

  • Die erste Zeile des Blocks um wahr zu sein, nach dem gesucht und der Block ersetzt werden, immer identisch

  • die Anzahl der Zeilen in dem Block zu suchen, und der Block zu ersetzen sind immer die gleiche

  • die Eingabedatei enthält immer die erste lin e des Blocks für die Suche nach genau einmal

  • Es muss nicht überprüft werden, dass die Zeilen in der Datei nach dem ersten im Block sind NULL,, und es ist ausreichend, nur die erste Zeile zu lokalisieren und entfernen Sie die folgenden Linien, was auch immer sie enthalten

Es funktioniert durch Lesen der Eingabedatei und Kopieren in STDOUT. Wenn es auf eine Zeile trifft, die die erste Zeile des Ersatzblocks enthält, liest es und verwirft Zeilen, bis die Anzahl der gelesenen Zeilen der Größe des Ersatzblocks entspricht. Dann wird der Text im Ersetzungsblock wird auf STDOUT gedruckt und das Kopieren fortgesetzt

use strict; 
use warnings 'all'; 
no warnings 'qw'; # avoid warning about commas in qw// 

my @replacement = qw/ 
    'ENTITLEMENT_EVS_V', 
    ENTITLEMENT_CATEGORY_CODE, 
    6, 
/; 

open my $fh, '<', $ARGV[0]; 

while (<$fh>) { 
    if (/$replacement[0]/) { 
     <$fh> for 1 .. $#replacement; 
     print "$_\n" for @replacement; 
    } 
    else { 
     print; 
    } 
} 

Dies funktioniert gut mit einigen Beispieldaten, die ich erstellt, aber ich habe keine Möglichkeit zu wissen, ob die Bestimmungen der oben aufgeführt ist, um Ihre aktuellen Daten gelten . Ich bin sicher, dass Sie mich wissen lassen, wenn braucht etwas

+0

Ich benutzte die zweite, wie es einfacher schien: –

+0

@SwarnaGowri: Zweite? Ich bin nicht klar, was du meinst. – Borodin

+0

Ich meinte deine Antwort :-) –

2

Ich bin nicht ganz klar, was Sie zu tun versuchen, aber ich habe versucht, das Wesen des Problems in eine in sich geschlossene Skript zu destillieren. In einem echten Programm würden Sie die Zuordnung von Variablennamen zu Kategorien und Codes lesen und analysieren, aber hier werde ich nur aus Strings lesen. Der Zweck davon ist zu zeigen, dass die Aufgabe ausgeführt werden kann, ohne Dateien zu schlürfen.

#!/usr/bin/env perl 

use strict; 
use warnings; 

my $entitlement_map_file = <<EOF_MAP_FILE; 
'ENTITLEMENT_EVS_V' 
ENTITLEMENT_CATEGORY_CODE 
6 
EOF_MAP_FILE 

my $entitlement_input_file = <<EOF_INPUT_FILE; 
'ENTITLEMENT_EVS_V', 
NULL, 
NULL, 
EOF_INPUT_FILE 

# read and parse the file containing mapping of 
# variables to category names and codes 

open my $map_fh, '<', \$entitlement_map_file 
    or die $!; 

my %map; 

while (my $var = <$map_fh>) { 
    chomp $var; 
    chomp(my $mnemonic = <$map_fh>); 
    chomp(my $code = <$map_fh>); 
    @{ $map{$var} }{qw(mnemonic code)} = ($mnemonic, $code); 
} 

close $map_fh; 

# read the input file, look up variable name in the map 
# if there, follow with category name and code 
# skip two lines from input, continue where you left off 

open my $in, '<', \$entitlement_input_file 
    or die $!; 

while (my $var = <$in>) { 
    $var =~ s/,\s+\z//; 
    next unless exists $map{ $var }; 

    for (1 .. 2) { 
     die unless <$in> =~ /^NULL/; 
    } 

    print join(",\n", $var, @{ $map{$var} }{qw(mnemonic code)}), "\n"; 
} 

close $in; 

Ausgang:

'ENTITLEMENT_EVS_V', 
ENTITLEMENT_CATEGORY_CODE, 
6

diese Verallgemeinerung ist als Übung dem Leser überlassen.

-1

hier eingestellt, was ich tat:

#!/usr/bin/env perl 
my ($lopen_fh, $lwrite_fh); 
my $l_stub_dir = "/home/cbdev2/imp/dev/src/deli/entfreeunits/config/entfreeunits/stubs"; 
my $l_stub = "DirectVariables_evEntlCategory.exp"; 
my $l_filename = "$l_stub_dir/$l_stub"; 
my $search_evs = 'ENTITLEMENT_EVS_V'; 
my $search_tre = 'ENTITLEMENT_TRE_V'; 

my @replacement_evs = qw/ 
    'ENTITLEMENT_EVS_V', 
    ENTITLEMENT_CATEGORY_CODE, 
    6, 
    /; 
my @replacement_tre = qw/ 
    'ENTITLEMENT_TRE_V', 
    ENTITLEMENT_CATEGORY_CODE, 
    6, 
    /; 

open ($lopen_fh, "<$l_filename") or die $!; 
open ($lwrite_fh, ">$l_filename.new") or die $!; 

while(<$lopen_fh>) { 
    if (/'ENTITLEMENT_EVS_V'/) { 
     <$lopen_fh> for 1 .. $#replacement_evs; 
     print $lwrite_fh " $_\n" for @replacement_evs; 
    } 
    elsif (/'ENTITLEMENT_TRE_V'/) { 
     <$lopen_fh> for 1 .. $#replacement_tre; 
     print $lwrite_fh " $_\n" for @replacement_tre; 
    } 
    else { 
     print $lwrite_fh $_; 
    } 
} 

close $lopen_fh; 
close $lwrite_fh; 

unlink($l_filename) or die "Failed to delete $l_filename: $!"; 
link("$l_filename.new", $l_filename) or die "Failed to copy $l_filename"; 
unlink("$l_filename.new") or die "Failed to delete $l_filename.new: $!";