Необходимо сохранить одну строку из удаления при некотором особом условии

#regex #perl

#регулярное выражение #perl

Вопрос:

Я написал код на perl, который способен выполнять поиск и удалять строку из файла (IN_FILE), который содержит «max_transition», когда выполняется условие «направление: вывод». После удаления строки код записывает измененный файл в другое местоположение.

Теперь мне нужно удалить строку «max_transition», когда будет выполнено условие «направление: вывод», а также где будет найдено слово «timing» в этой конкретной группе выводов.

IN_FILE, имеет выходной вывод «HIZIBI_79», HIZIBI_78 и HIZIBI. После запуска скрипта строка «max_transition» не должна удаляться из pin-кода «HIZIBI_79», «HIZIBI_78», потому что у этой группы pin-кодов нет «timing». Из pin-кода «HIZIBI» будет удалена только строка «max_transition», у нее есть группа «timing».

Есть идеи, как это реализовать?

Выходной файл должен выглядеть как OUT_FILE

 use warnings;
use strict;
my $inputfile = $ARGV[0]; # input lib FILE

if ($#ARGV!=0)
{
  print "USAGE :: perl max_tran_update.pl <<LIB_FILE>>  nn" ;
  exit(1);   
}

my $cmd = "mkdir  tmpdir;";
system ($cmd);

my $iline;
my $flag_outpin = 0;
my $out_pin_flag = 0;

open (INFILE,"<","$inputfile") || die "Can not open Input LIB File";
open (my $OPFILE,">","tmpdir/input_lib.lib") || die "Can not open Input Text File";

while ($iline = <INFILE>)
{
  chomp $iline;
  print $OPFILE "$ilinen";
  if (($iline =~m/^s*directions*:s*outputs*;/g))
  {
    $flag_outpin=1;
    while ($iline = <INFILE>)
    {
      if (($iline =~m/^s*directions*:s*inputs*;/g))
      {
        $flag_outpin=0;
      }
      if (($iline =~m/^s*directions*:s*outputs*;/g))
      {
        $flag_outpin=1;
      }
      if (($iline =~m/^s*max_transitions*:/g) amp;amp; ($flag_outpin == 1))
      {
        $iline =~ s/$iline//g ;
      }
      else 
      {
        print $OPFILE "$iline";
      }
    }
  }
}      
close INFILE;
close $OPFILE;
  

IN_FILE

   cell (lib_1) {
    dont_use : true ;
    dont_touch : true ;
    pin ("HIZIBI_IN_1") {
      direction : input ;
      clock : true ;
      max_transition : 1 ;
      capacitance : 12 ;
    }  
    pin ("HIZIBI_79")    {
      direction : output ;
      max_transition : 10;
      min_capacitance : 3 ;
    }              
    pin ("HIZIBI_IN_1") {
      direction : input ;
      clock : true ;
      max_transition : 1 ;
      capacitance : 1 ;
    }  
    pin ("HIZIBI_78")    {
      direction : output ;
      max_transition : 10;
      min_capacitance : 34 ;
      capacitance : 34 ;
    }            
    pin ("HIZIBI")    {
      direction : output ;
      clock : true ;
      max_transition : 20;
      related_power_pin : VDD ;
      related_ground_pin : VSS ;
      timing () {
        cell_fall (into_f1) {
          index_1("1,2,3,4,5") ;
          index_2("1,2,3,4,5") ;
          values("13, 13, 14, 16, 18",
                 "13, 14, 15, 16, 19",
                 "14, 15, 16, 17, 20",
                 "15, 15, 16, 18, 20",
                 "15, 16, 17, 18, 21") ;
        }  
      }  
    }
  }
  

OUT_FILE

 
  cell (lib_1) {
    dont_use : true ;
    dont_touch : true ;
    pin ("HIZIBI_IN_1") {
      direction : input ;
      clock : true ;
      max_transition : 1 ;
      capacitance : 12 ;
    }  
    pin ("HIZIBI_79")    {
      direction : output ;
      max_transition : 10;
      min_capacitance : 3 ;
    }              
    pin ("HIZIBI_IN_1") {
      direction : input ;
      clock : true ;
      max_transition : 1 ;
      capacitance : 1 ;
    }  
    pin ("HIZIBI_78")    {
      direction : output ;
      max_transition : 10;
      min_capacitance : 34 ;
      capacitance : 34 ;
    }            
    pin ("HIZIBI")    {
      direction : output ;
      clock : true ;
      related_power_pin : VDD ;
      related_ground_pin : VSS ;
      timing () {
        cell_fall (into_f1) {
          index_1("1,2,3,4,5") ;
          index_2("1,2,3,4,5") ;
          values("13, 13, 14, 16, 18",
                 "13, 14, 15, 16, 19",
                 "14, 15, 16, 17, 20",
                 "15, 15, 16, 18, 20",
                 "15, 16, 17, 18, 21") ;
        }  
      }  
    }
  }
  

Комментарии:

1. можете ли вы еще раз проверить требуемый вывод?. timing() не удаляется..

2. должна быть удалена строка «max_transition», а не блок синхронизации. «max_transition» должен быть удален, в какой группе контактов код найдет группу синхронизации. пожалуйста, смотрите, из pin HIZIBI удален max_transition.

3. Ваше простое решение «прочитайте строку, не печатайте ее при выполнении условий» не будет работать с вашим новым требованием, так как timing( это происходит после строки, которую вы хотите удалить. Вам придется переписать свой код, чтобы прочитать один pin(..) { ... } раздел целиком, решить, какие строки удалить, а затем перенести это в выходные данные. Поскольку у вас есть несколько операторов блочного типа, вам нужно будет либо посчитать открытые скобки, либо написать реальный анализатор для данного синтаксиса.

4. Код намного легче читать, если он имеет правильный отступ. Я только что исправил это для кода в этом вопросе. Пожалуйста, делайте это сами в будущем.

Ответ №1:

Это становится намного проще, если вы анализируете файл, чтобы иметь дело с одним pin { ... } разделом за раз. Этот код, похоже, справляется с задачей, но он, вероятно, хрупкий и вполне может сломаться при более сложном вводе.

 #!/usr/bin/perl

use strict;
use warnings;

# $counter will contain the number of unmatched { characters
# we have seen. If it's a positive number then we are in a
# pin section and we won't output anything until we get to
# the end of that section.
my $counter;
# Contains the contents of our current pin section.
my $pin = '';

# Read a line at a time from STDIN
while (<>) {
  # If we're not in a pin block, then
  # just print the line.
  if (!$counter and !/bpinb/) {
    print;
    next;
  }

  # Increment $counter by the number of { characters in the line
  $counter  = tr/{/{/;
  # Decrement $counter by the number of } characters in the line
  $counter -= tr/}/}/;

  # Append the current line to $pin
  $pin .= $_;

  # If $counter is 0 then we've just got to the end of a pin
  # block. The text of that block will be in $pin.
  if (!$counter) {
    # If $pin contains "directions : output" and "timings"...
    if ($pin =~ /directions*:s*output/ and $pin =~ /timings*/) {
      # ... then remove the "max_transitions" line from $pin
      $pin =~ s/s*max_transitions*:.*n//;
    }
    # Print the current $pin section
    print $pin;
    # And reset $pin to start the next section.
    $pin = '';
  }
}
  

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

 $ my_pin_filter < in_file > tmpdir/input_lib.lib
  

Комментарии:

1. Это лучший ответ @Dave Cross. Я считаю, что вы сделали наилучшим образом, как это должно быть. Нет, это не «хрупкий» код, отвечающий всем условиям, которые я здесь не упомянул. Спасибо, сэр 🙂

2. Мне очень, очень жаль, я должен нажать на галочку рядом с ответом. Только что я это сделал. Еще раз извините.

Ответ №2:

Попробуйте эту командную строку Perl

  perl -0777 -ne ' s/(pins*(". ?"?)s {. ?})/$x=$1;if($x=~m!timings*()! and $x=~m!direction : output!){$x=~s!^s*max_transition. ?n!!mg};$x/gse ; print ' anny_in.txt
  

Результаты:

  cell (lib_1) {
    dont_use : true ;
    dont_touch : true ;
    pin ("HIZIBI_IN_1") {
      direction : input ;
      clock : true ;
      max_transition : 1 ;
      capacitance : 12 ;
    }
    pin ("HIZIBI_79")    {
      direction : output ;
      max_transition : 10;
      min_capacitance : 3 ;
    }
    pin ("HIZIBI_IN_1") {
      direction : input ;
      clock : true ;
      max_transition : 1 ;
      capacitance : 1 ;
    }
    pin ("HIZIBI_78")    {
      direction : output ;
      max_transition : 10;
      min_capacitance : 34 ;
      capacitance : 34 ;
    }
    pin ("HIZIBI")    {
      direction : output ;
      clock : true ;
      related_power_pin : VDD ;
      related_ground_pin : VSS ;
      timing () {
        cell_fall (into_f1) {
          index_1("1,2,3,4,5") ;
          index_2("1,2,3,4,5") ;
          values("13, 13, 14, 16, 18",
                 "13, 14, 15, 16, 19",
                 "14, 15, 16, 17, 20",
                 "15, 15, 16, 18, 20",
                 "15, 16, 17, 18, 21") ;
        }
      }
    }
  }
  

Комментарии:

1. Уважаемый stack0114106, После запуска команды я получаю «timing: событие не найдено» из командной строки.

2. @anny..no у меня это сработало .. anny_in — это входной файл.. Попробуйте еще раз

3. Дорогой stack0114106, я пробовал несколько раз, но все еще получаю ту же проблему. Это связано с тем, что мы используем другую версию ОС? Я использую его в CentOS 6.7.

4. я запускаю его в cygwin .. можете ли вы проверить, присутствует ли r ?.. если да, удалите это и повторите попытку?

5. r отсутствует