Как я могу сыграть в эту подпрограмму Perl, которая выполняет замену? - PullRequest
4 голосов
/ 15 февраля 2010

У меня есть следующая подпрограмма в Perl, чтобы заменить "abc" на "xyz" в строке:

sub mySubst {
    my ($str) = @_;
    $str =~ s|abc|xyz|ig;
    return $str;    
}

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

Ответы [ 9 ]

8 голосов
/ 15 февраля 2010

То, что у вас есть, хорошо.

  • Вы извлекаете аргументы из переменной @_, делая копию, используя присвоение списка. Назначение списков - отличный способ сделать это (и в основном стандартным способом). Использование shift также будет работать, но изменения @_ (могут или не могут быть тем, что вы хотите.) Существует обсуждение PerlMonks о сдвиге vs @ _ , которые могут вас заинтересовать.
  • Вы используете именованную переменную при поиске и замене. В этом случае я предпочитаю именованные переменные, поскольку работа с магическими переменными в Perl позаботится.
  • Автоматическая работа с $ _ возможна, но отсутствие автоматического заполнения $ _ затрудняет получение правильной информации. Вам нужно будет сделать local $_ = shift; или local ($_) = @_;, что не добавляет много.)
  • Мне нравится, когда люди используют явное return. Это теплый нечеткий.
  • Кронштейны K & R. Хорошо. :)
  • Нет прототипа. Отлично. :)

Иди с этим. Я думаю, что вы на правильном пути.

6 голосов
/ 15 февраля 2010

Если вы ищете гольф, а не производственный код.

use strict;   ## Not really required ;)
use warnings; ## Not really required ;)
sub f{local$_=pop,s/foo/bar/ig;$_}
print f 'foobarbaz';
3 голосов
/ 15 февраля 2010

Вот как я бы сделал эту подпрограмму более идиоматически:

sub mySubst {
    (my $str = shift) =~ s|abc|xyz|ig;
    return $str;
}
3 голосов
/ 15 февраля 2010

Вы можете написать:

sub mySubst { (map { s|abc|xyz|ig; $_ } "$_[0]" )[0] }

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

1 голос
/ 26 февраля 2010

Никто еще не дал идиому Perl для этого. Это копирует поведение исходного кода путем изменения копии:

  (my $new_str = $old_str) =~ s/abc/xyz/ig;

Если бы мне пришлось поместить это в подпрограмму, что я считаю глупым для такой простой операции, я думаю, это будет:

 sub foo { (my $s = $_[0]) =~ s/abc/xyz/ig; $s }

Однако, если бы я делал что-то глупое, я бы не стал делать для этого именованную подпрограмму. Я бы сделал подпрограмму, чтобы сделать подпрограмму для меня, поэтому мне не нужно новое именованное подпрограмма для каждой возможной замены:

 sub make_sub {
      my( $regex, $replacement ) = @_;

      # season to taste with error checking
      sub {
          (my $s = $_[0]) =~ s/$regex/$replacement/ig; $s
          };
      }

 my $replacer = make_sub( qr/abc/, 'xyz' );

 my $new = $replacer->( $string );
1 голос
/ 15 февраля 2010

Я думаю слишком многословно звучит как недостаточно запутывания , с чем я не согласен. Что касается ужесточения Я бы предложил что-то вроде:

sub replaceBeginningWithEnd {
    my $text = shift;
    return if not defined($text);
    $text =~ s/abc/xyz/ig;
    return $text;    
}
  • Сделать имена более читабельными
  • Использовать условные обозначения (т. Е. / В отличие от |)
  • Проверка аргументов
0 голосов
/ 15 февраля 2010

Чтобы не менять оригиналы, вы можете написать

sub mySubst { map { (my $s=$_) =~ s|abc|xyz|ig; $s } @_ }

или

sub mySubst { my @a = @_; map { s|abc|xyz|ig; $_ } @a }

или заимствовать из ответа Синан, за исключением явного исключения временного массива:

sub mySubst { map { s|abc|xyz|ig; $_ } my(undef) = @_ }

но синтаксис все еще немного шумный. Поскольку он использует map, обязательно вызовите его в контексте списка:

my($result) = mySubst $str;  # NOT my $one = mySubst $str;

Если вы ожидаете, что в основном вызовете mySubst с одним аргументом, но хотите обрабатывать случаи с одним или несколькими аргументами, тогда вы можете написать

sub mySubst {
  s|abc|xyz|ig for my @a = @_;
  wantarray ? @a : $a[0];
}

но это снова вызывает заикание.


Если вы хотите обновить сам параметр, используйте семантику псевдонимов подпрограмм Perl, как описано в perlsub :

Массив @_ является локальным массивом, но его элементы являются псевдонимами для фактических скалярных параметров. В частности, если элемент $_[0] обновляется, соответствующий аргумент обновляется (или возникает ошибка, если он не обновляется).

Чтобы вы могли написать

sub mySubst { $_[0] =~ s|abc|xyz|ig }

или даже

sub mySubst { map { s|abc|xyz|ig; $_ } @_ }

Пример использования:

$str = "fooabcbar";
mySubst $str;
print $str, "\n";

Выход:

fooxyzbar
0 голосов
/ 15 февраля 2010

Вы можете опустить ключевое слово возврата:

sub mySubst {
    my ($str) = @_;
    $str =~ s|abc|xyz|ig;
    $str;    
}

Также можно использовать переменную по умолчанию ($_):

sub mySubst {
    local $_ = shift;  # or my starting from Perl 5.10
    s|abc|xyz|ig;
    $_;    
}
0 голосов
/ 15 февраля 2010

для чего нужен саб? просто сделай это так

$str =~ s|abc|xyz|ig;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...