как заменить указанную c строку записью, добавляя в файл - PullRequest
1 голос
/ 30 апреля 2020

у меня есть два файла. один из них - входной файл пользователя, а другой - оригинальный файл конфигурации. После сравнения двух файлов добавьте / удалите функции в моем исходном файле конфигурации.

входной файл пользователя: (показывается строка за строкой)

add:L28A:Z:W   #add--> DID ID --> Bin ID 
del:L28C:B:Q:X:
rpl:L38A:B:M:D:

исходный файл ввода

L28A:B:Q:M:X:
L28C:B:Q:M:X:
L38A:B:Q:M:X:

на основе входного файла пользователя, сначала выполняется функция добавления, а вторая - удалить функцию, а третье - заменить функцию.

, поэтому вывод для исходного входного текстового файла должен показывать:

L28A:B:Q:M:X:Z:W
L28C:M:
L38A:B:M:D:

, но мой код показывает:

L28A:B:Q:M:X:
L28C:B:Q:M:X:
L38A:B:Q:M:X:
L28A:B:Q:M:X:Z:W
L28C:M:
L38A:B:M:D:

как можно заменить три вышеупомянутые строки новыми изменяющимися строками?

use strict;
use warnings;
use File::Copy;
use vars qw($requestfile $requestcnt $configfile $config2cnt $my3file $myfile3cnt $new_file $new_filecnt @output);

my $requestfile = "DID1.txt"; #user's input file
my $configfile = "DID.txt";   #original config file
my $new_file = "newDID.txt";

readFileinString($requestfile, \$requestcnt);
readFileinString($configfile, \$config2cnt);
copy($configfile, $new_file) or die "The copy operation failed: $!";

while ($requestcnt =~ m/^((\w){3})\:([^\n]+)$/mig) #Each line from user request
{
    my $action = $1;
    my $requestFullLine = $3;
    while ($requestFullLine =~ m/^((\w){4})\:([^\n]+)$/mig) #Each line from user request
    {
         my $DID = $1; #DID
         my $requestBinList = $3; #Bin List in user request
         #my @First_values = split /\:/, $requestBinList;
         if ($config2cnt =~ m/^$DID\:([^\n]+)$/m) #configfile
         {
             my $ConfigFullLine = $1;  #Bin list in config
             my $testfile = $1;
             my @First_values = split /\:/, $ConfigFullLine;
             my @second_values = split /\:/, $requestBinList;
             foreach my $sngletter(@second_values) # Each line from user request
             {
                if( grep {$_ eq "$sngletter"} @First_values)
                {
                    print " $DID - $sngletter - Existing bin..\n\n";
                }
                else
                {
                    print "$DID - $sngletter - Not existing bin..\n\n";
                }
            }

            print "Choose option 1.Yes  2.No\n";
            my $option = <STDIN>;
            if ($option == 1) {
                open(DES,'>>',$configfile) or die $!;
                if($action eq 'add')
                {
                    $ConfigFullLine =~ s/$/$requestBinList/g;
                    my $add = "$DID:$ConfigFullLine";
                    print DES "$add\n" ;
                    print"New Added Bin Valu $add\n\n";
                }

                if ( $action eq 'del')
                {
                   foreach my $sngletter(@second_values){
                   $ConfigFullLine =~ s/$sngletter://g;
                }

                print DES "$DID:$ConfigFullLine\n";
                print "New Deleted Bin Value $DID:$ConfigFullLine\n\n";
            }

            if ( $action eq 'rpl')
            {
                my $ConfigFullLine = $requestBinList;
                my $replace = "$DID:$ConfigFullLine";
                print DES "$replace\n";
                print"Replace Bin Value $replace\n\n";
            }
        }
        elsif ($option == 2)
        {
            print"Start from begining\n";
        }
        else
        {
            print "user chose invalid process or input is wrong\n";
        }
    }
    else
    {
        print "New DID $DID detected\n";}
    }
}

sub readFileinString
{
    my $File = shift;
    my $string = shift;
    use File::Basename;
    my $filenames = basename($File);
    open(FILE1, "<$File") or die "\nFailed Reading File: [$File]\n\tReason: $!";
    read(FILE1, $$string, -s $File, 0);
    close(FILE1);
}

1 Ответ

2 голосов
/ 30 апреля 2020

Проблема здесь:

open(DES,'>>',$configfile) or die $!;

Вы открываете свой файл для добавления. Таким образом, вы получаете исходные данные, а затем ваши отредактированные данные.

Обновление: Похоже, у вас есть рабочее решение, но я подумал, что было бы интересно показать вам, как я буду напишите это.

Эта программа является фильтром Unix. То есть он читает из STDIN и пишет в STDOUT. Я нахожу это гораздо более гибким, чем жестко закодированные имена файлов. Вам также не нужно явно открывать файлы - это экономит время: -)

Также требуется параметр командной строки -c, сообщающий, какой файл содержит определения для редактирования. Итак, это называется так (при условии, что мы назвали программу edit_files:

$ edit_files -c edit_definitions.txt < your_input_file > your_output_file

И вот код.

#!/usr/bin/perl

use strict;
use warnings;

use Getopt::Std;

my %opts;
getopts('e:', \%opts);

my %edits = read_edits($opts{e});

while (<>) {
  chomp;
  my ($key, $val) = split /:/, $_, 2;   #/ stop faulty syntax highlight

  if (!exists $edits{$key}) {
    print "$_\n";
    next;
  }

  my $edit = $edits{$key};
  if ($edit->[0] eq 'add') {
    print "$_$edit->[1]\n";
  } elsif ($edit->[0] eq 'del') {
    $val =~ s/$_:// for split /:/, $edit->[1];  #/
    print "$key:$val\n";
  } elsif ($edit->[0] eq 'rpl') {
    print "$key:$edit->[1]\n";
  } else {
    warn "$edit->[0] is an invalid edit type\n";
    next;
  }
}

sub read_edits {
  my $file = shift;

  open my $edit_fh, '<', $file or die $!;

  my %edits;

  while (<$edit_fh>) {
    chomp;
    # Remove comments
    s/\s*#.*//;    #/
    my ($type, $key, $val) = split /:/, $_, 3;  #/

    $edits{$key} = [ $type, $val ];
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...