Perl эмулирует grep -n? - PullRequest
       29

Perl эмулирует grep -n?

0 голосов
/ 14 января 2012

Я новичок в Perl и хочу эмулировать grep -n так:

хочу:

# egrep -n 'malloc\(|free\(|printf\(' test.c
5:p = malloc(sizeof(char));
6:printf("Test\n");
7:free(p);

есть:

# perl grep.pl test.c
malloc\(line 7
free\(line 7
printf(

Processed 10 lines

Сценарий:

#!/usr/bin/perl
$verbose = 1;
@pattern = ('malloc\(', 'free\(', 'printf(');
$counter = 0;
open(FH, "<", $ARGV[1]) or die;

while (<>) {
  my $matches =  (@pattern[0-2]);
  $counter++;
  # print "line $counter:$_" if ($_ =~ /malloc\(/o);
  print join("line $counter\t\n",@pattern),"\n" if ($_ =~ /$matches/o);
  close (FH);
}
print "\n";
$verbose == 1 && print "Processed $counter lines\n";

Почему-то счетчик не так. Что мне здесь не хватает?

Ответы [ 5 ]

3 голосов
/ 14 января 2012

Ниже моя элементарная реализация grep в windows. Возможно, вы сможете настроить его на себя.

Номера строк в perl задаются как $. (см. perlvar ). При использовании алмазного оператора его можно просто напечатать как есть. Однако, если вы используете более одного файла, он не будет автоматически сбрасываться между файлами, и вам придется сделать немного магии:

while (<>) {
    # grep and print logic goes here
    # e.g. print "$.: $_" if grep_match();

    close ARGV if eof;  # this will reset $. for each file
}

Код:

use strict;
use warnings;
use v5.10;

my $pattern     = shift;

#use re 'debug';
# Refining the regex to allow using modifiers
$pattern =~ s#^/##;
if ( $pattern =~ s{/([^/]+)$}{} ) {
    $pattern = "(?$1)$pattern";
}

# Windows does not allow globbing, this is the fix
for (@ARGV) {
    unless (-e) {
        @ARGV = win_args(@ARGV);
        last;
    }
}

my $found;
while (<>) {
    if (/$pattern/) {
        unless ($found) {
            say "----- $ARGV -----";
        }
        print;
        $found = 1;
    }
    $found = 0 if eof;
}

sub win_args {
    return map glob, @_;
}
1 голос
/ 15 января 2012

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

Если это попытка заново изобрести колесо, необходимо четко указать добавленную стоимость.

Если это делается для эмуляции команды * nix в Windows, разве вы не удовлетворены тем, что уже есть ?.

1 голос
/ 14 января 2012

В вашем коде много ошибок, но вы должны начать с добавления

use strict;
use warnings;

в начале программы.Вам придется объявить все свои переменные, но сам Perl поможет вам решить большинство тривиальных задач.

$matches =  (@pattern[0-2]);

- это то же самое, что и

$matches =  $pattern[-2];

, который обращается ко второму элементу изконец массива - 'free (') - и присваивает его $ match, а это не то, что вам нужно. Вы можете использовать оператор pipe, который соответствует любому из выбранных шаблонов, если вы напишите

$matches = join '|', @pattern;

Кроме того, в

print join("line $counter\t\n",@pattern),"\n" if ($_ =~ /$matches/o);

я не думаю, что join делает то, что вы думаете. Вы объединяете все элементы массива с первой строкой в ​​качестве разделителя. Если вы просто хотите соответствующую строкутогда вам нужно

print "line $counter\t$_\n" if /$matches/o;

Это должно заставить вас работать, но, как я уже сказал, ваша программа не идеальна, и я показал минимальные необходимые изменения.

1 голос
/ 14 января 2012

Существует переменная с именем $. который содержит текущий номер строки, поэтому просто выведите значение этой переменной!

perldoc perlvar
0 голосов
/ 14 января 2012

Это должно сработать.Просто передайте шаблон с опцией имени файла (в противном случае используется стандартный ввод)

#!/usr/bin/perl

use strict;

my $pattern=shift;
my $fileName=shift;

my $fh;

if ($fileName)
{
   open $fh, $fileName or die "Unable to open file $fileName";
}
else
{
   open $fh, '-';
}

my $lineNumber = 1;
while (<$fh>)
{
   print sprintf("%4d %s", $lineNumber, $_) if (m%$pattern%);
   ++$lineNumber;
}

Просто создайте свой шаблон как (malloc\()|(free\(')|(printf\()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...