Как Вы используете sed от Perl?

Нет, строка работает немного как вектор в C ++ в том смысле, что, как только пространство зарезервировано в памяти, она не будет освобождена, если это явно не указано, или не превысит свою максимальную емкость. Это сделано для того, чтобы избежать максимально возможного изменения размера, потому что это будет означать выделение нового массива символов, копирование необходимых значений и удаление старого массива. Поддерживая зарезервированную память, удаление символа не требует создания нового массива, а перераспределение должно происходить только тогда, когда строка недостаточно велика, чтобы содержать то, что вы пытаетесь вставить в нее. Надеюсь, это поможет!

8
задан brian d foy 24 January 2010 в 00:15
поделиться

7 ответов

Я удивлен, что никто не упомянул s2p утилиту, которая переводит sed "сценарии" (Вы знаете, большую часть времени остроты) к допустимому жемчугу. (И существует a2p утилита для awk также...),

8
ответ дан 5 December 2019 в 04:31
поделиться

Предложение: Используйте регулярные выражения Perl и замены вместо grep или sed.

Это - approximentally тот же синтаксис, но более мощный. Также в конце это будет более эффективно, чем вызов дополнительного процесса sed.

25
ответ дан 5 December 2019 в 04:31
поделиться

Предположительно, Larry Wall записал Perl, потому что он нашел что-то, что было невозможно сделать с sed и awk. Другие ответы имеют это право, используют регулярные выражения Perl вместо этого. Ваш код будет иметь меньше внешних зависимостей, будет понятен большему количеству людей (база пользователей Perl намного больше, чем sed база пользователей), и Ваш код будет межплатформенным без дополнительной работы.

Править: Paul Tomblin связывает превосходную историю в своем комментарии к моему ответу. Я помещаю его здесь для увеличения, это - выдающееся положение.

"Henry Spencer, который сделал некоторые удивительные вещи с Awk, утверждал, что после демонстрации некоторого материала awk Larry Wall, Larry сказал, что не будет беспокоиться Perl, если бы он знал". – Paul Tomblin

4
ответ дан 5 December 2019 в 04:31
поделиться

Что-либо, что необходимо сделать с grep или sed, может быть сделано исходно в жемчуге более легко. Например (это примерно правильно, но вероятно неправильно):

my @linenumbers;
open FH "<$fileToProcess";
while (<FH>)
{
   next if (!m/textToFind/);
   chomp;
   s/^\([0-9]*\)[:].*/\1/;
   push @lineNumbers, $_;
}
14
ответ дан 5 December 2019 в 04:31
поделиться

Питание использования Luke:

$ echo -e "a\nb\na"|perl -lne'/a/&&print$.'
1
3

Таким образом, когда Вы хотите, то же думает, поскольку это замедляется и сверхсложный grep и sed комбинация можно сделать это намного более простой и быстрее в самом жемчуге:

my @linenumbers;
open my $fh, '<', $fileToProcess or die "Can't open $fileToProcess: $!";
while (<$fh>)
{
   /textToFind/ and push @lineNumbers, $.;
}
close $fh;

Или с теми же преступниками памяти как исходное решение

my @linenumbers = do {
    open my $fh, '<', $fileToProcess or die "Can't open $fileToProcess: $!";
    my $i;
    map { ( ++$i ) x /textToFind/ } <$fh>
};
2
ответ дан 5 December 2019 в 04:31
поделиться

Если у Вас было большое sed выражение, Вы могли использовать s2p, преобразовать его в a perl программа.

Если Вы работаете <s2p 's/^\([0-9]*\)[:].*/\1/p'>, это - то, что Вы получили бы:

#!/opt/perl/bin/perl -w
eval 'exec /opt/perl/bin/perl -S $0 ${1+"$@"}'
  if 0;
$0 =~ s/^.*?(\w+)[\.\w+]*$/$1/;

use strict;
use Symbol;
use vars qw{ $isEOF $Hold %wFiles @Q $CondReg
         $doAutoPrint $doOpenWrite $doPrint };
$doAutoPrint = 1;
$doOpenWrite = 1;
# prototypes
sub openARGV();
sub getsARGV(;\$);
sub eofARGV();
sub printQ();

# Run: the sed loop reading input and applying the script
#
sub Run(){
    my( $h, $icnt, $s, $n );
    # hack (not unbreakable :-/) to avoid // matching an empty string
    my $z = "\000"; $z =~ /$z/;
    # Initialize.
    openARGV();
    $Hold    = '';
    $CondReg = 0;
    $doPrint = $doAutoPrint;
CYCLE:
    while( getsARGV() ){
    chomp();
    $CondReg = 0;   # cleared on t
BOS:;
# s/^\([0-9]*\)[:].*/\1/p
{ $s = s /^(\d*)[:].*/${1}/s;
  $CondReg ||= $s;
  print $_, "\n" if $s;
}
EOS:    if( $doPrint ){
            print $_, "\n";
        } else {
        $doPrint = $doAutoPrint;
    }
        printQ() if @Q;
    }

    exit( 0 );
}
Run();

# openARGV: open 1st input file
#
sub openARGV(){
    unshift( @ARGV, '-' ) unless @ARGV;
    my $file = shift( @ARGV );
    open( ARG, "<$file" )
    || die( "$0: can't open $file for reading ($!)\n" );
    $isEOF = 0;
}

# getsARGV: Read another input line into argument (default: $_).
#           Move on to next input file, and reset EOF flag $isEOF.
sub getsARGV(;\$){
    my $argref = @_ ? shift() : \$_; 
    while( $isEOF || ! defined( $$argref = <ARG> ) ){
    close( ARG );
    return 0 unless @ARGV;
    my $file = shift( @ARGV );
    open( ARG, "<$file" )
    || die( "$0: can't open $file for reading ($!)\n" );
    $isEOF = 0;
    }
    1;
}

# eofARGV: end-of-file test
#
sub eofARGV(){
    return @ARGV == 0 && ( $isEOF = eof( ARG ) );
}

# makeHandle: Generates another file handle for some file (given by its path)
#             to be written due to a w command or an s command's w flag.
sub makeHandle($){
    my( $path ) = @_;
    my $handle;
    if( ! exists( $wFiles{$path} ) || $wFiles{$path} eq '' ){
        $handle = $wFiles{$path} = gensym();
    if( $doOpenWrite ){
        if( ! open( $handle, ">$path" ) ){
        die( "$0: can't open $path for writing: ($!)\n" );
        }
    }
    } else {
        $handle = $wFiles{$path};
    }
    return $handle;
}

# printQ: Print queued output which is either a string or a reference
#         to a pathname.
sub printQ(){
    for my $q ( @Q ){
    if( ref( $q ) ){
            # flush open w files so that reading this file gets it all
        if( exists( $wFiles{$$q} ) && $wFiles{$$q} ne '' ){
        open( $wFiles{$$q}, ">>$$q" );
        }
            # copy file to stdout: slow, but safe
        if( open( RF, "<$$q" ) ){
        while( defined( my $line = <RF> ) ){
            print $line;
        }
        close( RF );
        }
    } else {
        print $q;
    }
    }
    undef( @Q );
}

Не точно стоящий выполнения по маленьким выражениям.

1
ответ дан 5 December 2019 в 04:31
поделиться

Отредактированный: хорошо, я зафиксировал его теперь.

use File::Grep qw/fmap/;

my @lineNumbers = fmap { /$pattern/ ? $_[1] : () } $fileToProcess;
0
ответ дан 5 December 2019 в 04:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: