2015-06-12 2 views
0

я в состоянии сделать это в командной строке, и она работает:Perl: создание сценария как эффективный как PERL однострочника

~/Tools/perl/edif_extr_cell.pl design.edif nmos1p8v | perl -p -e 's/^/\n/ if /portImplementation|figure\s+device/;' | perl -n -000 -e 'print if /portImplementation/;' 

(в основном, извлекая часть файла EDIF).

Теперь я хочу воспользоваться этим. И мой сценарий внизу. Вопрос: может ли этот код быть более эффективным? Если чувствуете, что это очень неэлегантно. Я мог легко транслировать потоки в командной строке, но в сценарии я чувствую себя потерянным.

#!/usr/bin/perl -w -p 

BEGIN{ $file = '';} 

s/^/\n/ if /portImplementation|figure\s+device/; 
$file .= $_; 

END{ 
    $cmd = q{\rm -f /tmp/dump}.$$.'.txt'; 
    system($cmd); 
    open(OUT, ">/tmp/dump$$.txt"); 
    print OUT $file; 
    close OUT; 
    $out = `perl -n -000 -e 'print if /portImplementation/;' /tmp/dump$$.txt`; 
    system($cmd); 
    print $out; 
} 
+0

Не могли бы вы подать (упрощенный) входной образец? – choroba

ответ

3

Если я понимаю правильно, вы хотите, чтобы быть в состоянии сделать

~/Tools/perl/edif_extr_cell.pl design.edif nmos1p8v | myfilter 

В идеале, вы бы объединить два сценария Perl в одно, вместо того, чтобы запустить один сценарий, два экземпляра Perl, но это довольно сложно из-за изменения на $/ (через -00) и потому, что вы вставляете новые строки в первый фильтр.

Самый простой ответ:

#!/bin/sh 
perl -pe's/^/\n/ if /portImplementation|figure\s+device/' | 
    perl -00ne'print if /portImplementation/' 

Похоже, что вы пытаетесь написать эквивалент этой sh сценария в Perl. Это будет выглядеть следующим образом:

#!/usr/bin/perl 

use strict; 
use warnings; 

use IPC::Open qw(open3); 

# open3 has issues with lexical file handles. 

pipe(local *PIPE_READER, local *PIPE_WRITER) 
    or die($!); 

my $pid1 = open3('<&STDIN', '>&PIPE_WRITER', '>&STDERR', 
    'perl', '-pes/^/\n/ if /portImplementation|figure\s+device/'); 

my $pid2 = open3('<&PIPE_READER', '>&STDOUT', '>&STDERR', 
    'perl', '-00neprint if /portImplementation/'); 

waitpid($pid1); 
waitpid($pid2); 

я обычно рекомендую IPC :: RUN3 или IPC :: Run для запуска и взаимодействия с дочерними процессами, но с низким уровнем open3 делает трюк красиво в этой конкретной ситуации.

0

Я скачал случайный файл EDIF из GitHub, выполнив следующий сценарий на это дает тот же результат, как ваш код:

#! /usr/bin/perl 
use warnings; 
use strict; 

my @buffer; 
my $found; 
my $prepend = q(); 

while (<>) { 

    if (/portImplementation|figure\s+device/) { 
     if ($found && @buffer) { 
      print $prepend, @buffer; 
      $prepend = "\n"; 
     } 
     undef $found; 
     @buffer =(); 
    } 

    $found ||= /portImplementation/; 
    push @buffer, $_; 
} 

# Don't forget to output the last paragraph! 
print $prepend, @buffer if $found && @buffer; 
+0

Как насчет эффекта режима абзаца ('-00')? Вам нужно сбросить буфер на пустые строки. – ikegami

+0

@ikegami: во входном файле единственными пустыми строками были те, которые были созданы предыдущей заменой. – choroba

+0

Я не верю, что это правда вообще или даже в случае OP. Код явно разработан, чтобы не печатать другие элементы на том же уровне, что и «portImplementation» – ikegami

Смежные вопросы